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.09.28