探索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的工作原理和使用方法,你可以更好地利用它来实现代码增强和动态代理,为你的应用程序增加更多的灵活性和扩展性。

目录
相关文章
|
2月前
|
缓存 Java 测试技术
day27:Java零基础 - 动态代理
【7月更文挑战第27天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
26 2
day27:Java零基础 - 动态代理
|
17天前
|
开发者 C# 容器
【独家揭秘】当WPF邂逅DirectX:看这两个技术如何联手打造令人惊艳的高性能图形渲染体验,从环境搭建到代码实践,一步步教你成为图形编程高手
【8月更文挑战第31天】本文通过代码示例详细介绍了如何在WPF应用中集成DirectX以实现高性能图形渲染。首先创建WPF项目并使用SharpDX作为桥梁,然后在XAML中定义承载DirectX内容的容器。接着,通过C#代码初始化DirectX环境,设置渲染逻辑,并在WPF窗口中绘制图形。此方法适用于从简单2D到复杂3D场景的各种图形处理需求,为WPF开发者提供了高性能图形渲染的技术支持和实践指导。
43 0
|
25天前
|
设计模式 Java C++
揭秘!JDK动态代理VS CGLIB:一场关于Java代理界的‘宫心计’,你站哪队?
【8月更文挑战第24天】Java 动态代理是一种设计模式,允许在不改动原类的基础上通过代理类扩展功能。主要实现方式包括 JDK 动态代理和 CGLIB。前者基于接口,利用反射机制在运行时创建代理类;后者采用继承方式并通过字节码技术生成子类实现类的代理。两者在实现机制、性能及适用场景上有明显差异。JDK 动态代理适用于有接口的场景,而 CGLIB 更适合代理未实现接口的类,尽管性能更优但存在一些限制。开发者可根据需求选择合适的代理方式。
64 0
|
2月前
|
开发框架 Java Android开发
Java中的类反射与动态代理详解
Java中的类反射与动态代理详解
|
2月前
|
Java 数据安全/隐私保护
Java中的动态代理机制详解
Java中的动态代理机制详解
|
2月前
|
Java 数据库 Spring
Java编程问题之在测试中使用CGLIB创建代理类如何解决
Java编程问题之在测试中使用CGLIB创建代理类如何解决
|
2月前
|
缓存 Java 应用服务中间件
Java编程问题之重试机制问题之在CGLIB中设置目标对象类并创建代理类如何解决
Java编程问题之重试机制问题之在CGLIB中设置目标对象类并创建代理类如何解决
|
2月前
|
设计模式 Java 程序员
解析Java中的动态代理与静态代理的区别
解析Java中的动态代理与静态代理的区别
|
2月前
|
设计模式 Java C++
Java中的静态代理与动态代理详解
Java中的静态代理与动态代理详解
|
2月前
|
设计模式 Java C++
Java中的静态代理与动态代理详解
Java中的静态代理与动态代理详解