3 个真正有影响的场景(老哥 7+ 年必看)
场景 1:直接 new 出来的对象(不走 Spring 容器)
@Servicepublic class OrderService { public void process() { // ❌ 这个对象不是代理,没有事务、没有拦截 OrderService self = new OrderService(); self.process(); // 事务不生效 }}
这个问题不管 JDK 还是 CGLIB 都有(new 出来的对象不走容器)。
**但 CGLIB 升级后,这个坑更容易踩:
- JDK 代理时,代理对象实现接口,开发期容易发现(类型不对)
- CGLIB 代理时,代理对象继承实现类 ,
new出来的对象看着类型对 (都是OrderService),但实际是裸对象
场景 2:强制类型转换到具体类(CGLIB 升级的经典坑)
// ❌ 错误写法:JDK 代理不会报错,CGLIB 代理会 ClassCastExceptionpublic class AppConfig { @Autowired private OrderService orderService; // 注入的是代理对象 public void test() { OrderServiceImpl impl = (OrderServiceImpl) orderService; // ❌ // JDK 代理:ClassCastException(代理不是实现类子类) // CGLIB 代理:✅ 成功(代理是实现类子类) }}
等等,CGLIB 代理能转成功?这是好事还是坏事?
这是坏事 !因为 CGLIB 代理对象虽然继承 OrderServiceImpl,但重写了方法**(加事务拦截)**:
((OrderServiceImpl) proxy).createOrder()→ 走代理(有事务)- 表面上看着是 OrderServiceImpl,实际行为是代理的
这会导致 2 个问题:
1.绕过代理 (如果用 super.createOrder() 调用)
2.类型混乱(调试时看到是 OrderServiceImpl,实际行为是代理)
场景 3:Proxy.newProxyInstance 自定义代理(项目里要警惕)
public class CustomProxyFactory { public static <T> T createProxy(Class<T> interfaceClass, T target) { return (T) Proxy.newProxyInstance( // ✅ JDK 代理 interfaceClass.getClassLoader(), new Class<?>[] { interfaceClass }, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("Before: " + method.getName()); Object result = method.invoke(target, args); System.out.println("After: " + method.getName()); return result; } } ); }}
CGLIB 升级影响:
- 项目里自定义的 JDK 代理代码仍然能用
- 但和 Spring 管理的 Bean(CGLIB 代理)混用时,行为可能不一致
追问 :Spring Boot 2.0 为什么要把默认改成 CGLIB?
"3 个原因:
1.现代项目大多用 @Service/@Component ,很多类没有接口
2.JDK 代理必须有接口 ,CGLIB 不需要(更灵活)
3.CGLIB 性能已经接近 JDK 代理(CGLIB 3+ 优化很多)
Spring Boot 2.0 把默认改成 CGLIB,避免项目里出现'有接口用 JDK、没接口用 CGLIB'的混乱。"
记忆口诀
"CGLIB 继承类又实现接口,99% 项目无影响"
"final 类/方法/static,CGLIB 全都代理不了"
"JDK 代理只能 public,CGLIB 能 private,但建议显式 public"
"Spring Boot 2.0 默认 CGLIB 智能切换,3 个真坑要知道"
一句话总结
"Spring Boot 2.0 改 CGLIB 后,接口实现基本无影响(CGLIB 既继承类又实现接口)。
3 个真正有影响的场景:
1.直接 new 出来的对象(不走容器)
2.强制类型转换(CGLIB 行为不同)
3.自定义 Proxy.newProxyInstance(混用问题)