当前位置: 首页 > news >正文

JDK动态代理和CGLIB动态代理的区别?

大家好,我是锋哥。今天分享关于【JDK动态代理和CGLIB动态代理的区别?】面试题。希望对大家有帮助;

JDK动态代理和CGLIB动态代理的区别?

1000道 互联网大厂Java工程师 精选面试题-Java资源分享网

JDK动态代理和CGLIB动态代理是Java中实现代理模式的两种方式,它们的主要区别在于代理对象的生成方式和应用场景。以下是它们的具体区别:

1. 代理对象的生成方式

  • JDK动态代理

    • JDK动态代理是基于接口的代理,代理对象必须实现一个或多个接口。
    • 通过java.lang.reflect.Proxy类和InvocationHandler接口来创建代理对象。
    • 生成的代理对象是实现了接口的类。

    示例代码:

    public interface MyInterface {void doSomething();
    }public class MyInterfaceImpl implements MyInterface {public void doSomething() {System.out.println("Doing something!");}
    }public class MyInvocationHandler implements InvocationHandler {private Object target;public MyInvocationHandler(Object target) {this.target = target;}public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("Before method call");Object result = method.invoke(target, args);System.out.println("After method call");return result;}
    }public class Main {public static void main(String[] args) {MyInterface target = new MyInterfaceImpl();MyInterface proxy = (MyInterface) Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),new MyInvocationHandler(target));proxy.doSomething();}
    }
    

  • CGLIB动态代理

    • CGLIB(Code Generation Library)是基于类的代理,代理对象是通过继承目标类来实现的。
    • CGLIB使用字节码技术动态生成目标类的子类,并重写目标类的方法来创建代理对象。
    • 生成的代理类继承了目标类,因此不需要目标类实现接口。

    示例代码:

    public class MyClass {public void doSomething() {System.out.println("Doing something!");}
    }public class MyCglibProxy implements MethodInterceptor {private Object target;public MyCglibProxy(Object target) {this.target = target;}public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {System.out.println("Before method call");Object result = method.invoke(target, args);System.out.println("After method call");return result;}
    }public class Main {public static void main(String[] args) {MyClass target = new MyClass();Enhancer enhancer = new Enhancer();enhancer.setSuperclass(MyClass.class);enhancer.setCallback(new MyCglibProxy(target));MyClass proxy = (MyClass) enhancer.create();proxy.doSomething();}
    }
    

2. 是否依赖接口

  • JDK动态代理:必须依赖接口,目标类需要实现一个或多个接口。
  • CGLIB动态代理:不依赖接口,代理对象是通过继承目标类创建的,可以对普通类进行代理。

3. 性能差异

  • JDK动态代理:由于JDK动态代理依赖反射机制(Method.invoke()),在某些场景下性能较差,尤其是在方法调用频繁的情况下。
  • CGLIB动态代理:由于是通过继承目标类并重写方法来实现的,性能比JDK动态代理更高,但生成的代理类比较重,且需要使用字节码生成库(CGLIB),所以性能不如直接实现接口的JDK代理。

4. 生成的代理类的特点

  • JDK动态代理:生成的代理类实现了目标类的所有接口,代理类和目标类的实例是完全不同的对象。
  • CGLIB动态代理:生成的代理类是目标类的子类,代理类继承了目标类的方法,并重写了需要增强的方法。

5. 适用场景

  • JDK动态代理:适用于目标类实现了接口的情况。如果目标类没有实现接口,JDK动态代理不能使用。
  • CGLIB动态代理:适用于目标类没有接口的情况,或者你希望通过类继承的方式进行代理。但需要注意,CGLIB无法代理final类和final方法。

6. 代理对象的类型

  • JDK动态代理:生成的代理对象是接口类型的实例,实际调用会通过InvocationHandler来处理。
  • CGLIB动态代理:生成的代理对象是目标类的子类,代理对象是目标类的类型。

总结:

特性JDK动态代理CGLIB动态代理
代理方式基于接口的代理基于类的代理
是否需要接口需要接口不需要接口,使用类继承
性能相对较慢,使用反射更快,直接继承并重写方法
代理的对象类型代理类实现接口代理类是目标类的子类
适用场景目标类实现了接口的情况目标类没有接口或需要对类进行代理
final类的支持支持,final方法不可代理不支持,final类和final方法无法代理

选择使用JDK动态代理还是CGLIB动态代理,主要取决于你的应用场景。如果目标类已经实现了接口,且希望通过接口代理,JDK动态代理是更优选择;如果目标类没有接口,则需要使用CGLIB动态代理。

相关文章:

  • suricata增加单元测试编译失败
  • 3DGS-to-PC:3DGS模型一键丝滑转 点云 or Mesh 【Ubuntu 20.04】【2025最新版!!】
  • STM32 变量存储
  • window 显示驱动开发-指定 DMA 缓冲区的段
  • 2.3 定积分
  • 恰到好处TDR
  • #在 CentOS 7 中手动编译安装软件操作及原理
  • c#修改ComboBox当前选中项的文本
  • ExcelJS库的使用
  • vue2/3 中使用 @vue-office/docx 在网页中预览(docx、excel、pdf)文件
  • 关于nextjs中next-sitemap插件生成文件样式丢失问题及自定义样式处理
  • vue的table表格选择回显不显示
  • vue H5解决安卓手机软键盘弹出,页面高度被顶起
  • 网卡网孔速率的协商是如何进行的?
  • 【小记】word批量生成准考证
  • element中表格文字剧中可以使用的属性
  • 初识 Pandas:Python 数据分析的利器
  • 七、MyBatis-Plus高级用法:最优化持久层开发
  • 力扣2094题解
  • Stream Deck纯软件实现高性价比平替
  • 新剧|《藏海传》定档,《折腰》《人生若如初见》今日开播
  • 2024年度全国秋粮收购达3.45亿吨
  • 巴军事行动致印度70%电网瘫痪
  • “苏河超级管”调研:桥下公园“留白”很好,指引差点
  • 网络主播直播泄机密,别让这些“小事”成威胁国家安全的“突破口”
  • 俄罗斯今日将举行“胜利日”阅兵,有何看点?