Spring AOP 实现方式对比
Spring AOP 默认用 JDK 动态代理还是 CGLIB?为什么 @Transactional 自调用会失效?理解代理机制才能避开这些坑。
一、AOP 的核心概念
- 1.1 Aspect / JoinPoint / Advice / Pointcut / Weaving
- 1.2 Spring AOP vs AspectJ 的区别
- 1.3 Spring AOP 是基于代理的——只能拦截方法
二、JDK 动态代理
- 2.1 基于接口的代理——必须有接口
- 2.2
Proxy.newProxyInstance()原理 - 2.3
InvocationHandler.invoke()的实现 - 2.4 生成的代理类长什么样——
$Proxy0反编译
三、CGLIB 动态代理
- 3.1 基于类的代理——不需要接口
- 3.2
Enhancer和MethodInterceptor - 3.3
FastClass机制——避免反射 - 3.4 生成的代理类——继承目标类
- 3.5 final 方法和 final 类的限制
四、Spring 的代理选择策略
- 4.1 Spring Boot 1.x vs 2.x 的默认策略变化
- 4.2
spring.aop.proxy-target-class=true强制使用 CGLIB - 4.3 有接口时:JDK 动态代理
- 4.4 无接口时:CGLIB
- 4.5 同时有接口又有具体类依赖——
@EnableAspectJAutoProxy(proxyTargetClass=true)
五、自调用失效问题
- 5.1 什么是自调用——类内部方法调用
- 5.2 失效原因——调用的是
this.method()而非代理对象 - 5.3
AopContext.currentProxy()获取当前代理 - 5.4
@EnableAspectJAutoProxy(exposeProxy=true)暴露代理 - 5.5 另一种解法——把被调方法提取到另一个 Bean
六、AOP 源码核心流程
- 6.1
@EnableAspectJAutoProxy→@Import(AspectJAutoProxyRegistrar) - 6.2
AnnotationAwareAspectJAutoProxyCreator——BeanPostProcessor - 6.3
postProcessAfterInitialization()→wrapIfNecessary() - 6.4 代理创建的时机——在 Bean 初始化之后
七、实战案例
- 7.1 自定义
@Log注解 + AOP 实现方法日志 - 7.2 自定义
@RateLimit注解 + AOP 实现限流
八、总结
- 性能对比:CGLIB > JDK 动态代理
- 何时用哪个 + 自调用问题的解决方案
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 谜思录!