SpringAOP
Spring AOP相关概念
Spring的AOP实现底层就是对上面的动态代理的代码进行了封装,封装后我们只需要对需要关注的部分进行代码编写,并通过配置的方式完成指定目标的方法增强。
-
Target(目标对象) 要被增强的对象,一般是业务逻辑类的对象。 -
Proxy(代理) 一个类被 AOP 织入增强后,就产生一个结果代理类。 -
Aspect(切面) 表示增强的功能,就是一些代码完成的某个功能,非业务功能。是切入点和通知的结合。 -
Joinpoint(连接点) 所谓连接点是指那些被拦截到的点。在Spring中,这些点指的是方法(一般是类中的业务方法),因为Spring只支持方法类型的连接点。 -
Pointcut(切入点) 切入点指声明的一个或多个连接点的集合。通过切入点指定一组方法。被标记为 final 的方法是不能作为连接点与切入点的。因为最终的是不能被修改的,不能被增强的。 -
Advice(通知/增强)所谓通知是指拦截到 Joinpoint 之后所要做的事情就是通知。通知定义了增强代码切入到目标代码的时间点,是目标方法执行之前执行,还是之后执行等。通知类型不同,切入时间不同。通知的类型:前置通知,后置通知,异常通知,最终通知,环绕通知。 切入点定义切入的位置,通知定义切入的时间。 -
Weaving(织入). 是指把增强应用到目标对象来创建新的代理对象的过程。 spring 采用动态代理织入,而 AspectJ 采用编译期织入和类装载期织入。
- 切面的三个关键因素:
1、切面的功能–切面能干啥 2、切面的执行位置–使用Pointcut表示切面执行的位置 3、切面的执行时间–使用Advice表示时间,在目标方法之前还是之后执行。
AspectJ 对 AOP 的实现
对于 AOP 这种编程思想,很多框架都进行了实现。Spring 就是其中之一,可以完成面向切面编程。AspectJ 也实现了 AOP 的功能,且其实现方式更为简捷而且还支持注解式开发。所以,Spring 又将AspectJ 的对于 AOP 的实现也引入到了自己的框架中。 在 Spring 中使用 AOP 开发时,一般使用 AspectJ 的实现方式,AspectJ 是一个优秀面向切面的框架,它扩展了 Java 语言,提供了强大的切面实现。
注解方式实现AOP
开发阶段:关注核心业务和AOP代码
运行阶段:spring框架会在运行的时候将核心业务和AOP代码通过动态代理的方式编织在一起代理方式的选择:是否实现了接口:有接口就选择JDK动态代理;没有就选择CGLIB动态代理。
引入依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.3.9</version>
</dependency>
spring.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
">
<!-- 在beans中引入aop约束-->
<context:component-scan base-package="com.zhou.service"/>
<context:component-scan base-package="com.zhou.aop"/>
<aop:aspectj-autoproxy proxy-target-class="true"/>
<!-- xml方式实现aop-->
<aop:config>
<aop:pointcut id="pt1" expression="execution(* com.zhou.service..*.*(..))"/>
<aop:aspect ref="aop">
<aop:before method="before" pointcut-ref="pt1"/>
<aop:after-returning method="after" pointcut-ref="pt1" returning="result"/>
<aop:after-throwing method="exception" pointcut-ref="pt1" throwing="ex"/>
<aop:after method="myFinally" pointcut-ref="pt1"/>
</aop:aspect>
</aop:config>
</beans>
切面类
package com.zhou.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class Aop {
public void before(JoinPoint jp){
System.out.println("前置通知");
}
public void after(Object result){
System.out.println("后置通知");
}
public void exception(Throwable ex){
System.out.println("异常通知");
}
public void myFinally(){
System.out.println("最终通知");
}
}
核心业务类
package com.zhou.service;
import org.springframework.stereotype.Service;
@Service
public class TeamService implements IService{
@Override
public void add(int id, String name) {
System.out.println("TeamService-----add");
}
@Override
public boolean update(int num) {
System.out.println("TeamService-----update");
return true;
}
}
测试类
import com.zhou.service.IService;
import com.zhou.service.TeamService;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Mytest {
@Test
public void test1(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
TeamService teamService = (TeamService) applicationContext.getBean("teamService");
teamService.add(1,"sas");
}
}
测试结果:
|