Skip to content

AOP

AOP实现的原理

Spring AOP 的实现原理是基于动态代理和字节码操作的。

在编译时, Spring 会使用 AspectJ 编译器将切面代码编译成字节码文件。在运行时, Spring 会使用 Java 动态代理或 CGLIB 代理生成代理类,这些代理类会在目标对象方法执行前后插入切面代码,从而实现AOP的功能。

JDK动态代理、CGLIB代理

当bean的实现中存在接口或者是Proxy的子类,使用jdk动态代理;不存在接口,spring会采用CGLIB来生成代理对象

JDK 动态代理主要涉及到 java.lang.reflect 包中的两个类:Proxy 和 InvocationHandler

  • 通过bind方法建立代理与真实对象关系,通过Proxy.newProxyInstance(target)生成代理对象
  • 代理对象通过反射invoke方法实现调用真实对象的方法

Proxy 利用 InvocationHandler(定义横切逻辑) 接口动态创建 目标类的代理对象

AOP源码分析

  • @EnableAspectJAutoProxy给容器(beanFactory)中注册一个AnnotationAwareAspectJAutoProxyCreator对象;
  • AnnotationAwareAspectJAutoProxyCreator对目标对象进行代理对象的创建,对象内部,是封装JDK和CGlib两个技术,实现动态代理对象创建的(创建代理对象过程中,会先创建一个代理工厂,获取到所有的增强器(通知方法),将这些增强器和目标类注入代理工厂,再用代理工厂创建对象);
  • 代理对象执行目标方法,得到目标方法的拦截器链,利用拦截器的链式机制,依次进入每一个拦截器进行执行

AOP核心概念

  • 切面(aspect): 类是对物体特征的抽象,切面就是对横切关注点的抽象
  • 横切关注点:对哪些方法进行拦截,拦截后怎么处理,这些关注点称之为横切关注点
  • 连接点(joinpoint): 被拦截到的点,因为 Spring 只支持方法类型的连接点,所以在Spring 中连接点指的就是被拦截到的方法,实际上连接点还可以是字段或者构造器
  • 切入点(pointcut): 对连接点进行拦截的定义
  • 通知(advice): 所谓通知指的就是指拦截到连接点之后要执行的代码,通知分为前置、后置、异常、最终、环绕通知五类。
  • 目标对象:代理的目标对象
  • 织入(weave): 将切面应用到目标对象并导致代理对象创建的过程
  • 引入(introduction): 在不修改代码的前提下,引入可以在运行期为类动态地添加方法或字段

AOP应用场景

  • 记录日志
  • 监控性能
  • 权限控制
  • 事务管理
  • 线程池关闭等

注意事项

从Spring5.2.x开始,Spring AOP不再严格按照AspectJ定义的规则来执行advice,而是根据其类型按照从高到低的优先级进行执行:@Around,@Before ,@After,@AfterReturning,@AfterThrowing

因为未指定顺序,所以比较切面类的字符串str1.compareTo(str2)

所以在实际开发中,建议显式的指定好顺序

最佳实践

自定义注解实现限流

网站当前构建日期: 2024.06.25