cglib 和jdk 动态代理

本文深入探讨了Java动态代理与CGLIB的工作原理和使用场景。Java动态代理依赖反射机制,通过生成实现接口的匿名类并在调用前处理方法。CGLIB则采用字节码技术,生成目标类的子类并覆盖方法,适用于未实现接口的类。值得注意的是,CGLIB无法代理final方法。
  • java动态代理是利用反射机制生成一个实现代理接口的匿名类,
    • 在调用具体方法前调用InvokeHandler来处理。
    • JDK动态代理只能对实现了接口的类生成代理,而不能针对类

    • CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法(继承)

  • cglib动态代理是利用asm开源包,
    • 对代理对象类的class文件加载进来,
    • 通过修改其字节码生成子类来处理。
    • 唯一需要注意的是,CGLib不能对声明为final的方法进行代理,
      • 因为CGLib原理是动态生成被代理类的子类。

转载于:https://my.oschina.net/u/3847203/blog/3044447

### CGLIBJDK动态代理的区别及适用场景 #### 一、基本概念 CGLIB(Code Generation Library)是一种基于ASM字节码生成框架的工具库,它能够在运行时动态生成目标类的子类并覆盖其方法。与此不同的是,JDK动态代理利用Java反射机制,在运行时创建实现了指定接口的对象实例。 - **CGLIB**:通过继承的方式实现动态代理[^3]。 - **JDK动态代理**:仅支持对接口的代理,不支持对具体类的代理[^4]。 --- #### 二、主要区别 ##### 1. 实现原理 - **CGLIB**:采用字节码操作技术,生成目标类的子类,并重写其中的方法以实现代理功能[^2]。 - **JDK动态代理**:基于Java Reflection API,通过`InvocationHandler`拦截方法调用,从而完成代理逻辑。 ##### 2. 支持范围 - **CGLIB**:可以代理任意未被标记为final的类及其方法,即使该类没有实现任何接口也无妨。 - **JDK动态代理**:只能代理那些已经定义好的接口以及其实现类中的方法。 ##### 3. 性能表现 从性能角度来看,随着JDK版本升级,两者之间的差距逐渐缩小: - 在较新的JDK版本(如JDK7及以上),JDK动态代理的性能有了明显改善,而CGLIB的表现则趋于平稳甚至有所退步[^1]。 - 尽管如此,在某些特殊情况下(比如频繁调用少量方法的小型项目里),由于不需要加载额外的第三方库文件等原因,可能仍然会觉得CGLIB稍快一点。 ##### 4. 开发复杂度 - **CGLIB**:需要引入外部依赖项(即cglib本身的jar包以及其他关联组件如asm等)。此外,当处理一些特殊的构造函数或者静态字段的时候也会遇到更多挑战。 - **JDK动态代理**:完全内置到标准版java sdk之中,没有任何附加条件限制即可直接使用。 --- #### 三、适用场景分析 | 场景描述 | 推荐方案 | | --- | --- | | 需要代理已有的接口 | JDK动态代理 是最佳选择,因为它设计初衷就是为了简化这种需求下的开发工作量。| | 对象本身并没有提供明确的业务行为抽象层(也就是缺少对应的interface定义)| 此种情形下应该考虑运用CGLIB来进行增强控制[^5].| | 运行环境受限于内存资源紧张或者是追求极致效率的应用程序内部| 如果确认不会经常变更代码结构的话,则可以选择继续沿用传统的JDK方式; 否则建议切换至更灵活高效的解决方案——CGLIB[^2].| --- #### 四、总结说明 综上所述,虽然理论上讲CGLIB具备更强的功能特性并且在早期阶段确实展现出了优于前者的优势地位,但是考虑到实际应用过程中存在的各种约束因素之后就会发现它们各自都有适合自己的领域位置。因此,在决定选用哪一种类型的动态代理之前一定要充分权衡各方面利弊得失后再做定夺。 ```python # 示例代码展示如何分别使用两种不同的代理模式 import java.lang.reflect.Proxy; import net.sf.cglib.proxy.Enhancer; public class ProxyExample { public static void main(String[] args) throws Exception{ // 创建一个简单的服务类作为演示用途 HelloService helloServiceImpl=new HelloServiceImpl(); // 使用JDK动态代理 MyInvocationHandler handler = new MyInvocationHandler(helloServiceImpl); Class<?> proxyClass=Proxy.getProxyClass( HelloService.class.getClassLoader(), new Class[]{HelloService.class}); Object obj=proxyClass.getConstructor(new Class[]{ InvocationHandler.class }).newInstance(handler); ((HelloService)obj).sayHello(); // 使用CGLIB动态代理 Enhancer enhancer=new Enhancer(); enhancer.setSuperclass(HelloServiceImpl.class); enhancer.setCallback((MethodInterceptor)(obj1, method, objects, methodProxy)->methodProxy.invokeSuper(obj1,objects)); HelloService cglibProxy=(HelloService)enhancer.create(); cglibProxy.sayHello(); } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值