07.spring-aop概念和原理

61 阅读4分钟

AOP概念

AOP(Aspect Orient Programming),直译过来就是 面向切面编程,AOP 是一种编程思想,是面向对象编程的一种补充。面向切面编程,可以实现在不修改源代码的情况下给程序动态统一添加额外功能的一种技术,往往应用于实现日志处理,权限控制,性能检测,事务控制等场景中。如下图:

image-20230228151631934

AOP实现的底层原理就是学习过的动态代理。在有接口的情况下,使用JDK动态代理,在没有接口的情况下使用cglib动态代理。

AOP中的术语

术语名称说明
Joint point(连接点)类里面那些可以被增强的方法
Pointcut(切入点)实际被增强的方法
Advice(通知)对切入点增强的具体内容
Target(目标)被增强功能的对象(被代理的对象)
Aspect(切面)切入点+通知的结合。表现为把通知应用到切入点的过程
Weaving(织入)指把增强代码应用到目标上,生成代理对象的过程。

Spring AOP通知分类

通知说明
before(前置通知)通知方法在目标方法调用之前执行
after(后置通知)通知方法在目标方法返回或异常后调用
after-returning(返回后通知)通知方法会在目标方法返回后调用
after-throwing(抛出异常通知)通知方法会在目标方法拋出异常后调用
around(环绕通知)目标方法调用之前和返回之后。 @Before + 方法执行 + @After

SpringAOP与AOP联盟

AOP联盟,一群热爱技术的人觉得AOP思想不错,于是打算促进和标准化AOP,定制了一套标准,推动AOP和JAVA发展。那么AOP联盟的标准是什么呢?spring-aop jar包中有个目录org.aopalliance,其中存在几个接口,即是AOP联盟提供的AOP标准API。不过spring在此基础之上又增加一些类,丰富了AOP定义及其使用。AOP联盟如果定义的是具体接口的话,SpringAOP可以看成是这些接口的实现。

image-20230301145610536

SpringAOP 与Aspectj关系

AspectJ也是AOP的一个具体实现。SpringAOP实现的方式和它完全不同,Aspectj更像是静态代理;而SpringAOP是动态代理。但是Aspectj定义了一套AOP的API非常好,直观易用。所以Spring引入了Aspectj,并且使用部分注解,比如@AspceJ、@Before、@PonitCut这些注解,都是AspectJ中的注解。这就需要引入Aspectj的jar包了。

切入点表达式

AspectJ定义了专门的表达式用于指定切入点。表达式的原型如下:

execution([modifiers-pattern]  访问权限类型
​
       ret-type-pattern       返回值类型
​
       [declaring-type-pattern]  全限定性类名
​
       name-pattern(param-pattern)  方法名(参数名)
​
       [throws-pattern]  抛出异常类型
)

切入点表达式要匹配的对象就是目标方法的方法名。表达式中加[]的部分表示可省略的部分,其他2部分表示不可省略的部分,各部分之间用空格分开。在其中可以使用一下符号:

符号含义
*0至多个任意字符
..用在方法参数中,表示任意多个参数;用在包名后表示当前包及其子包
+用在类名后,表示当前类及其子类;用在接口后,表示当前接口及其实现类

举几个例子:

execution(public * *(..)) 指定切入点为:任意公共方法

execution(* .service. .*(..)) 指定只有一级包下的service子包下所有类(接口)中所有方法为切入点

execution(* ..service. .*(..)) 指定所有包下的service子包下所有类(接口)中所有方法为切入点

execution(* .SomeService. (..)) 指定只有一级包下的SomeService类(接口)中所有方法为切入点

execution(* ..SomeService. (..)) 指定所有包下的SomeService类(接口)中所有方法为切入点

记忆印记

  • AOP是面向切面,常用的场景有记录日志、权限验证、事务管理、性能检测等
  • AOP底层其实就是动态代理,在不修改原业务代码的基础上进行功能扩展或者修改
  • SpringAOP是AOP联盟定义的规范的一个具体实现
  • SpringAOP因为结合了AspectJ框架,所以需要需要引用该依赖
  • 切入点表达式记不住,用的时候查一下