Spring AOP
spring AOP 目前只支持对方法进行切面编程,如果想实现对字段的拦截,可以使用AspectJ
主要功能:日志记录,性能统计,安全控制,事务处理,异常处理
AOP概念:
名称 | 说明 |
切面(Aspect) | 一个关注点的模块化,这个关注点可能会横切多个对象 |
连接点(Joinpoint) | 程序执行过程中的某个特定的点。例如类初始化、方法执行、方法调用、字段调用或处理异常等等,Spring只支持方法执行连接点。 |
通知(Advice) | 在切面的某个特定的连接点上执行的动作。(通知定义了切面是什么以及何时使用。描述了切面要完成的工作和何时需要执行这个工作。) |
切入点(Pointcut) | 匹配连接点的断言,在AOP中通知和一个切入点的表达式。(例如某个类或方法的名称,Spring中允许我们方便的用正则表达式来指定) |
引入(Introduction) | 再不修改类代码的前提下,为类添加新的方法和属性。(也称为内部类型声明,为已有的类添加额外新的字段或方法,Spring允许引入新的接口(必须对应一个实现)到所有被代理对象(目标对象)) |
目标对象(Target Object) | 被一个或多个切面所通知的对象。(需要被织入横切关注点的对象,即该对象是切入点选择的对象,需要被通知的对象,从而也可称为“被通知对象”;由于Spring AOP 通过代理模式实现,从而这个对象永远是被代理对象) |
AOP代理(AOP Proxy) | AOP框架创建的对象,用来实现切面契约(aspect contract)(包括通知方法执行等功能) |
织入(Weaving) | 把切面连接到其他的应用程序类型或者对象上,并创建一个被通知的对象, 分为:编译时织入、类加载时织入、执行时织入。(将切面应用到目标对象从而创建出AOP代理对象的过程,织入可以在编译期、类装载期、运行期进行) |
AOP 的配置方式分为三种:API配置,XML配置,注解配置(下面以注解为例)
AOP的使用步骤:
1、创建方面类
2、声明配置切入点
3、创建通知类(方便统一管理),并将通知类中的通知与某一切入点关联
实例
使用注解@Aspect表示声明一个切面,但该注解不支持自动扫描,所以需要添加一个@Component注解,并且方面类本省不能成为目标类
官方解释如下:
创建切面:
@Component @Aspect public class MyAspectJ { public MyAspectJ() { System.out.println("检测到AOP切面->"+this.getClass().getName()); } }
AOP支持的切入点指示符(PCD)
spring AOP支持的如下:
名称 | 说明 |
execution | 用于匹配方法执行连接点。这是使用Spring AOP时使用的主要切入点指示符。 |
within | 限制匹配某些类型中的连接点(使用Spring AOP时在匹配类型中声明的方法的执行) |
this | 限制与连接点的匹配(使用Spring AOP时执行方法),其中bean引用(Spring AOP代理)是给定类型的实例。 |
target | 限制匹配连接点(使用Spring AOP时执行方法),其中目标对象(被代理的应用程序对象)是给定类型的实例。 |
args | 限制与连接点的匹配(使用Spring AOP时执行方法),其中参数是给定类型的实例。 |
@target | 限制与连接点的匹配(使用Spring AOP时执行方法),其中执行对象的类具有给定类型的注释。 |
@args | 限制与连接点的匹配(使用Spring AOP时执行方法),其中传递的实际参数的运行时类型具有给定类型的注释。 |
@within | 限制匹配到具有给定注释的类型中的连接点(使用Spring AOP时执行在具有给定注释的类型中声明的方法)。 |
@annotation | 限制连接点的匹配,其中连接点的主题(在Spring AOP中执行的方法)具有给定的注释。 |
bean | 将连接点的匹配限制为特定的命名Spring bean或一组命名的Spring bean |
spring 提供了一些表达式示例:
在切面中声明切入点:
@Component @Aspect public class MyAspectJ { public MyAspectJ() { System.out.println("检测到AOP切面->"+this.getClass().getName()); } @Pointcut("execution(* getUserInfo(..))") public void nameIsGetUserInfoMethod() {} @Pointcut("execution(* com.aop.servilce.UserService.*(..))") public void anyPointcut(){} }
spring APO 共提供了5中通知:
@Before |
前置通知,在切入点匹配的目标对象执行前执行 |
@After |
后置通知,在切入点匹配的目标对象执行后执行 |
@AfterReturning |
正常返回通知,在切入点匹配的目标对象执行后执行,并可以获取目标对象的某个方法的返回结果 |
@AfterThrowing |
异常返回通知,在切入点匹配的目标对象执行出现异常时执行,并可以获取目标对象出现异常的具体类型 |
@Around |
环绕通知,环绕通知围绕在连接点前后,比如一个方法调用的前后。能在方法调用前后自定义一些操作。环绕通知还需要负责决定是继续处理join point(调用ProceedingJoinPoint的proceed方法)还是中断执行 |
创建通知:
@Component @Aspect public class MyAdvice { public MyAdvice() { System.out.println("检测到AOP通知类->"+this.getClass().getName()); } @Before("com.aop.util.aop.aspectj.MyAspectJ.nameIsGetUserInfoMethod() && args(id,name)") public void before(String id,String name){ System.out.println("前置通知!"+"---------------"+id+name); }
参考连接:
https://docs.spring.io/spring/docs/5.1.4.BUILD-SNAPSHOT/spring-framework-reference/core.html#aop