Spring Boot之CGLIB
本文最后更新于 2025-11-20,文章内容可能已经过时。
一、CGLIB 是否还在更新?
CGLIB(Code Generation Library) 是一个老牌的 Java 字节码生成库,它底层依赖 ASM。虽然 CGLIB 的更新频率较低,但它并未停止维护,只是因为其核心功能已经非常稳定,所以新版本发布较少。
- 最新稳定版为 3.3.0(发布于 2020 年),目前仍被 Spring Framework 和 Spring Boot 广泛使用。
- Spring Boot 并不直接依赖 CGLIB,而是通过 Spring Framework 的 spring-core 模块间接引入(Spring 自 3.x 起已将 CGLIB 内嵌并重打包为
org.springframework.cglib,避免版本冲突)。 - 因此,即使官方 CGLIB 项目更新缓慢,Spring 团队会自行维护和适配其内嵌版本,确保兼容性和安全性。
✅ 结论:CGLIB 虽然更新慢,但在 Spring 生态中依然活跃且可靠。
二、Spring Boot 中的 AOP 默认使用的是 JDK 动态代理还是 CGLIB?
答案:Spring Boot 2.x 及以上版本,默认使用 CGLIB 动态代理。
具体说明:
| 版本 | 默认代理方式 | 原因 |
|---|---|---|
| Spring Boot 1.x | JDK 动态代理(有接口时) / CGLIB(无接口时) | 与传统 Spring 一致 |
| Spring Boot 2.x ~ 3.x | 强制默认 CGLIB | 避免类型转换问题、提升性能、无需强制实现接口 |
技术细节:
-
Spring Boot 2 开始,在自动配置类 AopAutoConfiguration 中默认设置:
spring.aop.proxy-target-class=true这个配置表示强制使用基于类的代理(即 CGLIB),而不是基于接口的 JDK 代理。
-
即使你的 Bean 实现了接口,Spring Boot 2+ 仍然会用 CGLIB 生成代理类(如 YourServiceEnhancerBySpringCGLIBxxx)。
-
如果你显式设置:
spring.aop.proxy-target-class=false那么对于实现了非空接口的类,会回退到 JDK 动态代理;但没有接口的类仍会使用 CGLIB(因为 JDK 代理无法代理纯类)。
补充:为什么 Spring Boot 2+ 改用 CGLIB?
-
避免类型转换异常
JDK 代理返回的对象只能赋值给接口类型,不能赋值给实现类。例如:@Autowired private MyServiceImpl service; // ❌ 注入失败!JDK 代理对象不是 MyServiceImpl 类型而 CGLIB 代理对象是目标类的子类,可以赋值给实现类变量。
-
性能更好
CGLIB 使用字节码生成 + FastClass 机制,避免反射调用,性能优于 JDK 代理。 -
开发更自由
不再强制要求业务类必须实现接口。
总结
| 问题 | 答案 |
|---|---|
| CGLIB 是否停止更新? | 官方更新慢,但 Spring 内嵌维护,仍在广泛使用 |
| Spring Boot AOP 默认代理方式? | 2.x 起默认 CGLIB,可通过 spring.aop.proxy-target-class=false 切回 JDK 代理(仅对接口有效) |
如有需要,也可以通过调试查看代理对象的类名(含 $$EnhancerBySpringCGLIB 或 com.sun.proxy.$Proxy)来判断实际使用的代理类型。
- 感谢你赐予我前进的力量

