JDK 动态代理和 CGLIB 动态代理有什么区别?
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 项目 → 让框架自动选择理解两者的区别有助于在实际项目中做出合适的选择

相关新闻

基于Spring Boot的投资理财系统设计与实现(任务书)

基于Spring Boot的投资理财系统设计与实现(任务书)

本科毕业论文(设计)任务书 学院:数学与数据科学学院 学生姓名 专业班级 信计213 学号 校内指导教师姓名 职称/职务 副教授 签名 校外指导教师姓名 职称/职务 技术经理 签名 论文题目 基于Spring Boot的投资理财系统设计与实现 起始日期 2024年9月~2025年5月 一、论文(设…

2026/7/5 23:32:52 阅读更多 →
【Docker高级篇】吃透容器编排:Swarm vs K8s 核心差异,为后续K8s学习打牢基础

【Docker高级篇】吃透容器编排:Swarm vs K8s 核心差异,为后续K8s学习打牢基础

🍃 予枫:个人主页📚 个人专栏: 《Java 从入门到起飞》《读研码农的干货日常》💻 Debug 这个世界,Return 更好的自己! 引言 在上一篇博客中,我们聊过Docker如何依托Linux内核特性实现容器隔离与资…

2026/7/6 0:02:45 阅读更多 →
【Docker高级篇】吃透Docker CI/CD集成:从代码提交到镜像部署,一步到位不踩坑

【Docker高级篇】吃透Docker CI/CD集成:从代码提交到镜像部署,一步到位不踩坑

🍃 予枫:个人主页📚 个人专栏: 《Java 从入门到起飞》《读研码农的干货日常》💻 Debug 这个世界,Return 更好的自己! 引言 做Docker运维或开发的同学,一定踩过“手动构建镜像、手动部署应用”的…

2026/5/17 5:37:57 阅读更多 →

最新新闻

Windows任务栏终极清理指南:用RBTray一键隐藏窗口到系统托盘

Windows任务栏终极清理指南:用RBTray一键隐藏窗口到系统托盘

Windows任务栏终极清理指南:用RBTray一键隐藏窗口到系统托盘 【免费下载链接】rbtray A fork of RBTray from http://sourceforge.net/p/rbtray/code/. 项目地址: https://gitcode.com/gh_mirrors/rb/rbtray 你是否厌倦了Windows任务栏上密密麻麻的图标&…

2026/7/6 0:01:17 阅读更多 →
H2 与 MySQL 单元测试兼容性:5 个关键 SQL 语句差异与规避方案

H2 与 MySQL 单元测试兼容性:5 个关键 SQL 语句差异与规避方案

H2与MySQL单元测试兼容性:5个关键SQL语句差异与规避方案1. 单元测试中的数据库兼容性挑战在Java开发领域,单元测试是保证代码质量的重要环节。当应用涉及数据库操作时,测试环境的搭建往往成为开发者的痛点。H2数据库因其轻量级、内存模式和快…

2026/7/6 0:01:17 阅读更多 →
免费二维码修复工具终极指南:三步拯救损坏二维码

免费二维码修复工具终极指南:三步拯救损坏二维码

免费二维码修复工具终极指南:三步拯救损坏二维码 【免费下载链接】qrazybox QR Code Analysis and Recovery Toolkit 项目地址: https://gitcode.com/gh_mirrors/qr/qrazybox 你是否曾经面对一个损坏的二维码束手无策?模糊、破损、打印质量差的二…

2026/7/5 23:59:17 阅读更多 →
AsrTools:如何用一款开源工具在5分钟内完成专业级语音转文字?

AsrTools:如何用一款开源工具在5分钟内完成专业级语音转文字?

AsrTools:如何用一款开源工具在5分钟内完成专业级语音转文字? 【免费下载链接】AsrTools ✨ AsrTools: Smart Voice-to-Text Tool | Efficient Batch Processing | User-Friendly Interface | No GPU Required | Supports SRT/TXT Output | Turn your au…

2026/7/5 23:57:17 阅读更多 →
YOLOv8融合坐标注意力机制优化目标检测性能

YOLOv8融合坐标注意力机制优化目标检测性能

1. YOLOv8与坐标注意力机制融合背景目标检测作为计算机视觉的基础任务,其发展始终围绕精度与速度的平衡展开。YOLO系列算法因其"一次检测"的设计理念,在实时性上具有先天优势。YOLOv8作为该系列的最新代表作,通过更深的网络结构、更…

2026/7/5 23:55:16 阅读更多 →
基于深度学习的工程图纸形位公差自动识别技术解析

基于深度学习的工程图纸形位公差自动识别技术解析

1. 项目背景与核心价值在机械制造和工程图纸设计领域,形位公差的标注与识别一直是影响生产效率的关键环节。传统的人工识别方式不仅耗时费力,而且容易因视觉疲劳导致误判。我们团队开发的"简会图纸识别系统"正是为了解决这一行业痛点而生。这套…

2026/7/5 23:53:15 阅读更多 →

日新闻

H2 与 MySQL 单元测试兼容性:5 个关键 SQL 语句差异与规避方案

H2 与 MySQL 单元测试兼容性:5 个关键 SQL 语句差异与规避方案

H2与MySQL单元测试兼容性:5个关键SQL语句差异与规避方案1. 单元测试中的数据库兼容性挑战在Java开发领域,单元测试是保证代码质量的重要环节。当应用涉及数据库操作时,测试环境的搭建往往成为开发者的痛点。H2数据库因其轻量级、内存模式和快…

2026/7/6 0:01:17 阅读更多 →
Windows任务栏终极清理指南:用RBTray一键隐藏窗口到系统托盘

Windows任务栏终极清理指南:用RBTray一键隐藏窗口到系统托盘

Windows任务栏终极清理指南:用RBTray一键隐藏窗口到系统托盘 【免费下载链接】rbtray A fork of RBTray from http://sourceforge.net/p/rbtray/code/. 项目地址: https://gitcode.com/gh_mirrors/rb/rbtray 你是否厌倦了Windows任务栏上密密麻麻的图标&…

2026/7/6 0:01:17 阅读更多 →

周新闻

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱,支持下载视频、番剧等等各类资源 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools …

2026/7/5 0:03:34 阅读更多 →
威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型的陌生现状在忙碌疲惫的一天里,参与了关于混合后量子密码学的讨论,应付端点攻击找茬的人,还参与留言板讨论后,发现“威胁模型”对多数人仍是陌生概念,且多被当作时髦用语。有趣的相关画作有一幅由 Embyr 创作的…

2026/7/5 0:03:34 阅读更多 →
渗透测试入门指南:从零基础到实战环境搭建

渗透测试入门指南:从零基础到实战环境搭建

1. 从“看热闹”到“入门”:我理解的渗透测试到底是什么?每次看到新闻里说某个大公司的数据被“黑”了,或者某个网站被攻击导致服务瘫痪,你是不是和我一样,心里会冒出两个念头:一是“这黑客真厉害”&#x…

2026/7/5 0:07:38 阅读更多 →

月新闻