Spring AOP基于动态代理实现,1. 当目标类实现接口时,默认使用JDK动态代理,通过Proxy和InvocationHandler在运行时创建代理对象并织入切面逻辑;2. 若目标类未实现接口,则采用CGLIB代理,通过生成子类并重写非final方法实现增强;3. Spring根据配置自动选择代理方式,可通过proxyTargetClass属性强制使用CGLIB;4. 在容器初始化时,Spring扫描切点、创建代理对象并替换原始bean,调用时由代理执行通知逻辑。该机制运行时织入,无需修改源码,适合企业级应用。

Spring AOP 的实现主要基于动态代理技术,它在不修改原始类代码的前提下,为对象的方法添加额外的逻辑(如日志、事务、权限等)。其核心机制依赖于两种代理方式:JDK 动态代理和 CGLIB 代理。
1. JDK 动态代理
当目标类实现了至少一个接口时,Spring AOP 默认使用 JDK 动态代理。它通过 java.lang.reflect.Proxy 类和 InvocationHandler 接口来创建代理对象。
具体流程如下:
- Spring 拿到目标对象的接口信息
- 使用 Proxy 创建一个新的代理类,该类也实现相同的接口
- 调用方法时,实际执行的是 InvocationHandler 中的 invoke() 方法
- 在 invoke() 中可以加入前置、后置通知,再调用原方法
2. CGLIB 代理
如果目标类没有实现任何接口,Spring 会使用 CGLIB 库来生成子类实现代理。CGLIB(Code Generation Library)通过继承目标类并重写其方法来实现增强。
立即学习“Java免费学习笔记(深入)”;
关键点包括:
- CGLIB 在运行时动态生成目标类的子类
- 子类覆盖所有非 final 的方法,在其中插入切面逻辑
- 因此目标类不能是 final 的,方法也不能是 final 或 private
3. Spring 如何选择代理方式
Spring 会根据配置和类结构自动决定使用哪种代理:
- 如果目标对象实现了接口,默认使用 JDK 代理
- 可以通过 proxy-target-class="true" 强制使用 CGLIB
- 在注解驱动下(@EnableAspectJAutoProxy),同样可通过 proxyTargetClass 属性控制
例如:
@EnableAspectJAutoProxy(proxyTargetClass = true)
这会让所有情况都走 CGLIB 代理。
4. 实际工作流程简述
当你定义了一个切面(@Aspect)和通知(@Before, @After 等)后,Spring 会在容器初始化阶段:
- 扫描所有匹配的切点(Pointcut)
- 为目标 bean 创建相应的代理对象(JDK 或 CGLIB)
- 将原始 bean 替换为代理 bean 放入容器
- 外部调用时,实际执行的是代理对象的方法,从而触发切面逻辑
基本上就这些。Spring AOP 不是靠修改字节码或编译期织入,而是运行时生成代理对象来实现横切逻辑的注入,这种方式简单、安全、易于调试,适合大多数企业级应用场景。











