spring aop默认优先使用jdk动态代理(目标类实现接口时),否则回退cglib代理;可通过配置spring.aop.proxy-target-class: true或@enableaspectjautoproxy(proxytargetclass = true)强制启用cglib,但需注意final类/方法不可代理、类型变为子类及自我调用失效等问题。

Spring AOP 默认使用 JDK 动态代理,但前提是目标类实现了至少一个接口;如果目标类没有实现任何接口,Spring 会自动回退到 CGLIB 代理。
默认代理行为的判断逻辑
Spring 在创建 AOP 代理时,按以下规则自动选择:
- 目标类实现了接口 → 默认用 JDK 动态代理(生成实现相同接口的代理对象)
- 目标类未实现接口 → 必须用 CGLIB 代理(生成目标类的子类)
- 即使目标类实现了接口,Spring 仍允许你主动切换为 CGLIB
强制启用 CGLIB 代理的两种方式
适用于需要统一代理策略、或目标类含 final 方法/需代理具体类类型等场景:
-
配置文件方式:在 application.yml 中添加
spring.aop.proxy-target-class: true -
注解方式:在 Spring Boot 启动类上添加
@EnableAspectJAutoProxy(proxyTargetClass = true)
关键注意事项
启用 CGLIB 后需留意以下限制:
- CGLIB 无法代理 final 类 或 final 方法(子类无法重写)
- 代理对象的运行时类型是目标类的子类,而非接口类型 —— 若代码中强依赖接口类型(如
if (proxy instanceof XxxService)),可能出问题 - 自我调用失效:在被代理类内部直接调用本类另一个方法(如
this.methodB()),AOP 增强不会触发,因为没经过代理对象
验证代理类型的小技巧
可在切面或业务代码中打印代理对象实际类名:
System.out.println(targetObject.getClass().getName());
- JDK 代理输出类似:
com.sun.proxy.$Proxy65 - CGLIB 代理输出类似:
com.example.ServiceImpl$$EnhancerBySpringCGLIB$$a1b2c3d4
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











