探索Java动态代理:深入了解CGLib

简介: 了解什么是CGLib,它如何实现动态代理和代码增强,以及它与Java标准动态代理的比较。

1. 介绍CGLib

在Java领域,CGLib(Code Generation Library)是一个强大的字节码操作库,常用于实现动态代理和类的增强。与Java标准库的动态代理不同,CGLib在代理时不需要目标类实现接口,这使得它在某些场景下更加灵活。

2. CGLib动态代理的基本原理

CGLib的动态代理机制是通过生成目标类的子类来实现的。当你需要代理一个类时,CGLib会创建一个该类的子类,并在子类中重写需要代理的方法。这允许你在方法调用前后插入自定义逻辑,实现方法的增强。

3. CGLib的使用步骤

  • 1.引入CGLib库的依赖
<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.3.0</version>
</dependency>
  • 创建一个Enhancer对象,用于生成代理类
  • 设置目标类和拦截器(MethodInterceptor
  • 设置拦截器
  • 测试


4. 实例:使用CGLib实现方法增强

通过一个实际的示例,演示如何使用CGLib实现方法的增强。展示如何创建拦截器(MethodInterceptor),并在方法调用前后插入自定义的逻辑,从而实现对方法的增强。

    创建一个Enhancer对象,用于生成代理类

        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(DemoServiceImpl.class);
        enhancer.setCallback( new TargetInterceptor());
  • 设置目标类和拦截器(MethodInterceptor)
publicclassDemoServiceImp{
publicvoidride(){
System.out.println("骑车啦");
    }
}

publicTargetInterceptorimplementsMethodIntercetor{
@OverridepublicObjectintercept(Objecto, Methodmethod, Object[] objects, MethodProxymethodProxy) throwsThrowable {
System.out.println("===intercept before ===");
Objectresult=methodProxy.invokeSuper(o,objects);
System.out.println("===intercept after====");
returnresult;
    }
}

使用Enhancer创建代理对象

@Test
public void testEnhancer(){
  //设置class的字节码的生成目录 方便查看
  System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY,"/Users/xxxx/Documents/workspaces/Staging/");
  Enhancer enhancer = new Enhancer();
  enhancer.setSuperclass(DemoServiceImpl.class);
  enhancer.setCallback( new TargetInterceptor());
  DemoServiceImpl demoServiceImpl = (DemoServiceImpl)enhancer.create();
  //拿到的其实是已经增强的类
  demoServiceImpl.ride();
}

image.png


再去查看下class 生成的信息:

image.png

第一个是代理类,可以大概的看下情况

image.png


5. 与Java标准动态代理的对比

     cglib 其实跟jdk proxy 都是为了在运行中解决代理的问题。

    cglib 是来自于第三方包,基于ASM来实现的,内部比较复杂 jdk 是自带的,会随着jdk版本升级与更新

    最大的区别是cglib 可以直接操作没有实现接口的类,相当于jdk proxy来说,

1.无接口限制
      2.继承代理: 字节码中可以看出是直接extends xxx 生成的代理类

3.调优性能优化在CGLIB中,方法调用被转发到目标方法的方式更加直接,不需要通过InvocationHandlerinvoke方法来间接调用。这样可以避免一层反射调用

4.缓存机制: CGLIB在生成代理类时会缓存已经生成过的类,避免重复生成。这在创建多个相同代理类实例时可以提高性能。JDK动态代理在每次生成新的代理实例时都会重新生成相应的字节码。

     使用场景:目标实现了接口,希望代理接口的方法,使用jdk proxy. AOP(日志,事务)

                       想要不需要实现接口的代理 在一定程度提升性能,那么就用cglib

6. CGLib的局限性

cglib局限性在于它是通过继承的方式来实现代理的,但是在日常开发中,会存在final修饰的情况,方法不能修改,变量不能修改 类不能被继承,也就意味着无法通过cglib进行增强,故不支持final 修饰的场景。遇到这种情况的时候,可以适当的转换思维,用jdk proxy

7. 总结

结尾: CGLib作为一个强大的字节码操作库,为Java动态代理提供了一种灵活且功能丰富的方式。通过深入了解CGLib的工作原理和使用方法,你可以更好地利用它来实现代码增强和动态代理,为你的应用程序增加更多的灵活性和扩展性。

目录
相关文章
|
1月前
|
Java
JAVA 静态代理 & 动态代理
【11月更文挑战第14天】静态代理是一种简单的代理模式实现,其中代理类和被代理类的关系在编译时已确定。代理类实现与被代理类相同的接口,并持有被代理类的实例,通过调用其方法实现功能增强。优点包括代码结构清晰,易于理解和实现;缺点是对于多个被代理类,需为每个类编写相应的代理类,导致代码量大增,维护成本高。动态代理则在运行时动态生成代理类,更加灵活,减少了代码冗余,但可能引入性能损耗和兼容性问题。
|
2月前
|
设计模式 Java API
[Java]静态代理与动态代理(基于JDK1.8)
本文介绍了代理模式及其分类,包括静态代理和动态代理。静态代理分为面向接口和面向继承两种形式,分别通过手动创建代理类实现;动态代理则利用反射技术,在运行时动态创建代理对象,分为JDK动态代理和Cglib动态代理。文中通过具体代码示例详细讲解了各种代理模式的实现方式和应用场景。
36 0
[Java]静态代理与动态代理(基于JDK1.8)
|
2月前
|
Java
深入理解Java动态代理
深入理解Java动态代理
92 1
|
2月前
|
Java
Java代码解释静态代理和动态代理的区别
### 静态代理与动态代理简介 **静态代理**:代理类在编译时已确定,目标对象和代理对象都实现同一接口。代理类包含对目标对象的引用,并在调用方法时添加额外操作。 **动态代理**:利用Java反射机制在运行时生成代理类,更加灵活。通过`Proxy`类和`InvocationHandler`接口实现,无需提前知道接口的具体实现细节。 示例代码展示了两种代理方式的实现,静态代理需要手动创建代理对象,而动态代理通过反射机制自动创建。
|
2月前
|
设计模式 缓存 Java
从源码学习Java动态代理|8月更文挑战
从源码学习Java动态代理|8月更文挑战
|
5月前
|
缓存 Java 测试技术
day27:Java零基础 - 动态代理
【7月更文挑战第27天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
45 2
day27:Java零基础 - 动态代理
|
4月前
|
开发者 C# 容器
【独家揭秘】当WPF邂逅DirectX:看这两个技术如何联手打造令人惊艳的高性能图形渲染体验,从环境搭建到代码实践,一步步教你成为图形编程高手
【8月更文挑战第31天】本文通过代码示例详细介绍了如何在WPF应用中集成DirectX以实现高性能图形渲染。首先创建WPF项目并使用SharpDX作为桥梁,然后在XAML中定义承载DirectX内容的容器。接着,通过C#代码初始化DirectX环境,设置渲染逻辑,并在WPF窗口中绘制图形。此方法适用于从简单2D到复杂3D场景的各种图形处理需求,为WPF开发者提供了高性能图形渲染的技术支持和实践指导。
299 0
|
4月前
|
设计模式 Java C++
揭秘!JDK动态代理VS CGLIB:一场关于Java代理界的‘宫心计’,你站哪队?
【8月更文挑战第24天】Java 动态代理是一种设计模式,允许在不改动原类的基础上通过代理类扩展功能。主要实现方式包括 JDK 动态代理和 CGLIB。前者基于接口,利用反射机制在运行时创建代理类;后者采用继承方式并通过字节码技术生成子类实现类的代理。两者在实现机制、性能及适用场景上有明显差异。JDK 动态代理适用于有接口的场景,而 CGLIB 更适合代理未实现接口的类,尽管性能更优但存在一些限制。开发者可根据需求选择合适的代理方式。
206 0
|
5月前
|
Java 数据库 Spring
Java编程问题之在测试中使用CGLIB创建代理类如何解决
Java编程问题之在测试中使用CGLIB创建代理类如何解决
|
5月前
|
缓存 Java 应用服务中间件
Java编程问题之重试机制问题之在CGLIB中设置目标对象类并创建代理类如何解决
Java编程问题之重试机制问题之在CGLIB中设置目标对象类并创建代理类如何解决