JDK 动态代理 vs CGLIB 动态代理1. 核心区别概览特性JDK 动态代理CGLIB 动态代理实现原理反射机制字节码生成ASM代理对象实现接口继承目标类代理目标只能代理接口可以代理类和接口性能创建快执行稍慢创建慢执行快JDK 版本JDK 原生支持需要第三方库限制不能代理 final 类不能代理 final 类和方法Spring 默认优先使用无接口时使用2. 实现原理对比2.1 JDK 动态代理原理┌─────────────────────────────────────────┐ │ JDK 动态代理工作流程 │ ├─────────────────────────────────────────┤ │ 1. Proxy.newProxyInstance() │ │ ↓ │ │ 2. 运行时生成代理类实现接口 │ │ ↓ │ │ 3. 所有方法调用 → InvocationHandler │ │ ↓ │ │ 4. 通过反射调用目标方法 │ └─────────────────────────────────────────┘生成的代理类结构// JDK 动态生成的代理类简化版publicfinalclass$Proxy0extendsProxyimplementsUserService{public$Proxy0(InvocationHandlerh){super(h);}publicvoidaddUser(Stringname){try{// 调用 InvocationHandlersuper.h.invoke(this,m3,newObject[]{name});}catch(Throwablee){// 异常处理}}privatestaticMethodm3;static{m3Class.forName(UserService).getMethod(addUser,String.class);}}2.2 CGLIB 动态代理原理┌─────────────────────────────────────────┐ │ CGLIB 动态代理工作流程 │ ├─────────────────────────────────────────┤ │ 1. Enhancer.create() │ │ ↓ │ │ 2. 字节码生成子类继承目标类 │ │ ↓ │ │ 3. 重写所有非 final 方法 │ │ ↓ │ │ 4. 方法调用 → MethodInterceptor │ │ ↓ │ │ 5. 直接调用目标方法FastClass │ └─────────────────────────────────────────┘生成的代理类结构// CGLIB 动态生成的代理类简化版publicclassUserService$$EnhancerByCGLIB$$12345678extendsUserService{privateMethodInterceptorinterceptor;publicvoidaddUser(Stringname){MethodInterceptorvar10000this.interceptor;if(var10000null){super.addUser(name);}else{// 调用拦截器var10000.intercept(this,CGLIB$addUser$0$Method,newObject[]{name},CGLIB$addUser$0$Proxy);}}// 保存原始方法引用finalvoidCGLIB$addUser$0(Stringname){super.addUser(name);}}3. 代码实现对比3.1 JDK 动态代理示例importjava.lang.reflect.InvocationHandler;importjava.lang.reflect.Method;importjava.lang.reflect.Proxy;// 接口必须interfaceUserService{voidaddUser(Stringname);voiddeleteUser(Stringname);}// 实现类classUserServiceImplimplementsUserService{publicvoidaddUser(Stringname){System.out.println(添加用户: name);}publicvoiddeleteUser(Stringname){System.out.println(删除用户: name);}}// JDK 动态代理publicclassJdkProxyDemo{publicstaticvoidmain(String[]args){UserServicetargetnewUserServiceImpl();// 创建代理UserServiceproxy(UserService)Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),newInvocationHandler(){OverridepublicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{System.out.println([JDK] 前置增强);Objectresultmethod.invoke(target,args);System.out.println([JDK] 后置增强);returnresult;}});proxy.addUser(张三);}}3.2 CGLIB 动态代理示例importnet.sf.cglib.proxy.Enhancer;importnet.sf.cglib.proxy.MethodInterceptor;importnet.sf.cglib.proxy.MethodProxy;// 目标类不需要接口classUserService{publicvoidaddUser(Stringname){System.out.println(添加用户: name);}publicvoiddeleteUser(Stringname){System.out.println(删除用户: name);}}// CGLIB 动态代理publicclassCglibProxyDemo{publicstaticvoidmain(String[]args){EnhancerenhancernewEnhancer();enhancer.setSuperclass(UserService.class);// 设置父类enhancer.setCallback(newMethodInterceptor(){OverridepublicObjectintercept(Objectobj,Methodmethod,Object[]args,MethodProxyproxy)throwsThrowable{System.out.println([CGLIB] 前置增强);Objectresultproxy.invokeSuper(obj,args);// 调用父类方法System.out.println([CGLIB] 后置增强);returnresult;}});UserServiceproxy(UserService)enhancer.create();proxy.addUser(张三);}}4. 详细对比4.1 代理目标// ✅ JDK只能代理接口interfaceInterfaceA{}classClassAimplementsInterfaceA{}InterfaceAjdkProxy(InterfaceA)Proxy.newProxyInstance(ClassA.class.getClassLoader(),ClassA.class.getInterfaces(),// 必须是接口handler);// ❌ JDK不能直接代理类ClassAjdkProxy2(ClassA)Proxy.newProxyInstance(ClassA.class.getClassLoader(),ClassA.class.getInterfaces(),// 空数组或接口handler);// 运行时错误// ✅ CGLIB可以代理类EnhancerenhancernewEnhancer();enhancer.setSuperclass(ClassA.class);// 设置父类ClassAcglibProxy(ClassA)enhancer.create();// ✅ CGLIB也可以代理接口Enhancerenhancer2newEnhancer();enhancer2.setSuperclass(InterfaceA.class);InterfaceAcglibProxy2(InterfaceA)enhancer2.create();4.2 性能对比publicclassPerformanceTest{publicstaticvoidmain(String[]args){// 测试创建代理的性能longstartSystem.currentTimeMillis();for(inti0;i10000;i){// JDK 代理创建Proxy.newProxyInstance(...);}System.out.println(JDK 创建耗时: (System.currentTimeMillis()-start));// CGLIB 代理创建startSystem.currentTimeMillis();for(inti0;i10000;i){EnhancerenhancernewEnhancer();enhancer.create();}System.out.println(CGLIB 创建耗时: (System.currentTimeMillis()-start));// 测试方法调用性能// JDK: 反射调用稍慢// CGLIB: FastClass 机制更快}}性能特点创建代理JDK CGLIBJDK 更快方法调用CGLIB JDKCGLIB 更快内存占用CGLIB JDKCGLIB 需要生成更多类4.3 限制对比// JDK 限制finalclassFinalClass{}// final 类// ❌ JDK 不能代理因为没有接口// CGLIB 限制classMyClass{publicfinalvoidfinalMethod(){}// final 方法}EnhancerenhancernewEnhancer();enhancer.setSuperclass(MyClass.class);MyClassproxy(MyClass)enhancer.create();proxy.finalMethod();// ❌ 不会被拦截直接调用原方法5. Spring 中的选择策略5.1 Spring AOP 代理选择ConfigurationEnableAspectJAutoProxy(proxyTargetClassfalse)// 默认 falsepublicclassAopConfig{// proxyTargetClass false: 优先使用 JDK 动态代理// proxyTargetClass true: 强制使用 CGLIB}Spring 的选择逻辑┌─────────────────────────────────────┐ │ Spring AOP 代理选择策略 │ ├─────────────────────────────────────┤ │ 目标类有接口 │ │ ├─ 是 → 使用 JDK 动态代理 │ │ └─ 否 → 使用 CGLIB │ │ │ │ proxyTargetClass true │ │ └─ 是 → 强制使用 CGLIB │ └─────────────────────────────────────┘5.2 实际示例// 场景 1有接口使用 JDK 代理interfaceOrderService{voidcreateOrder(StringorderId);}ServiceclassOrderServiceImplimplementsOrderService{publicvoidcreateOrder(StringorderId){System.out.println(创建订单: orderId);}}// Spring 会使用 JDK 动态代理OrderServiceproxycontext.getBean(OrderService.class);System.out.println(proxy.getClass().getName());// 输出: com.sun.proxy.$Proxy123// 场景 2无接口使用 CGLIBServiceclassPaymentService{publicvoidpay(StringorderId){System.out.println(支付订单: orderId);}}// Spring 会使用 CGLIBPaymentServiceproxycontext.getBean(PaymentService.class);System.out.println(proxy.getClass().getName());// 输出: com.example.PaymentService$$EnhancerBySpringCGLIB$$4566. 使用建议6.1 选择 JDK 动态代理的场景// ✅ 推荐目标类有接口interfaceRepository{voidsave(Objectentity);}classUserRepositoryimplementsRepository{publicvoidsave(Objectentity){// 实现}}// ✅ 推荐需要代理多个接口interfaceServiceA{}interfaceServiceB{}classMultiServiceimplementsServiceA,ServiceB{}// ✅ 推荐关注创建性能// 需要频繁创建代理对象时6.2 选择 CGLIB 的场景// ✅ 推荐目标类没有接口classUtilityService{publicvoiddoSomething(){// 实现}}// ✅ 推荐需要代理类的方法非接口方法classBaseService{publicvoidcommonMethod(){}// 不在接口中}// ✅ 推荐关注方法调用性能// 代理对象会被频繁调用时7. 常见问题7.1 循环依赖问题ServiceclassServiceA{AutowiredprivateServiceBserviceB;}ServiceclassServiceB{AutowiredprivateServiceAserviceA;}// 使用 CGLIB 可以解决循环依赖// 因为 CGLIB 代理的是类可以注入代理对象7.2 类型转换问题// JDK 代理interfaceMyInterface{}classMyClassimplementsMyInterface{}MyInterfaceproxy(MyInterface)Proxy.newProxyInstance(...);// ✅ 可以转换为接口类型// MyClass obj (MyClass) proxy; // ❌ 不能转换为实现类// CGLIB 代理MyClassproxy(MyClass)enhancer.create();// ✅ 可以转换为类类型// MyInterface obj (MyInterface) proxy; // ✅ 也可以转换为接口8. 总结维度JDK 动态代理CGLIB 动态代理核心机制反射字节码生成代理对象实现接口继承类适用场景有接口的类无接口的类创建性能快慢调用性能慢快Spring 默认优先使用无接口时使用final 限制不能代理 final 类不能代理 final 方法依赖JDK 原生cglib 库选择建议有接口 → 优先 JDK 动态代理无接口 → 使用 CGLIB关注创建性能 → JDK 动态代理关注调用性能 → CGLIBSpring 项目 → 让框架自动选择理解两者的区别有助于在实际项目中做出合适的选择