• 2种动态代理方式的性能测试(JDK1.8 JDK > Cglib)


    目录

    动态代理

    JDK动态代理实现

    cglib动态代理

    测试

    创建代理对象的性能测试

    调用代理对象方法的性能测试

    总结

    Cglib执行速度比JDK快? 不同jdk版本不一样。

    JDK 1.8  动态代理 JDK > Cglib


    动态代理

    JDK动态代理实现

    技术:java反射

    前提:代理的类实现了接口。

    通过newProxyInstance()函数获得proxy对象,这个对象就代理了实现了这个接口所有的类,然后使用这个代理对象即可。 代理对象会自动调用相应的方法。比如

    • IRpcHelloService RpcHello = RpcProxy.create(IRpcHelloService.class);

    • System.out.println(RpcHello.hello("Tom老师"));

    RpcHello IRpcHelloService.class这个接口的代理类,IRpcHelloServiceImpl实现了这个接口,那么RpcHello.hello("Tom老师")就相当于调用了IRpcHelloServiceImpl中的hello方法。

    newProxyInstance,方法有三个参数:

    loader: 用哪个类加载器去加载代理对象

    interfaces:动态代理类需要实现的接口

    h:动态代理方法在执行时,会调用h里面的invoke方法去执行

    1. public class ProxyHost implements InvocationHandler {
    2. private Object target;
    3. // 注入一个实现类
    4. public void setTarget(Object target) {
    5. this.target = target;
    6. }
    7. // 根据实现类 拿到其实现的方法
    8. public Object getProxy(){
    9. return Proxy.newProxyInstance(this.getClass().getClassLoader(),
    10. target.getClass().getInterfaces(),this);
    11. }
    12. // 在使用时直接调用方法即可
    13. // 调用时就会通过 invoke来实现
    14. @Override
    15. public Object invoke(Object proxy,Method method,Object[] args) throws Throwable {
    16. System.out.println("调用方法前的日志");// 在调用原对象的方法时 可以增强
    17. Object result = method.invoke(target,args);
    18. System.out.println("调用方法后的日志");
    19. return result;
    20. }
    21. }

    cglib动态代理

    需要引入相关的依赖 或者导入相关的包。

    1. public class ProxyFactory implements MethodInterceptor {
    2. //维护一个目标对象
    3. private Object target;
    4. //构造器,传入一个被代理的对象
    5. public ProxyFactory(Object target) {
    6. this.target = target;
    7. }
    8. //返回一个代理对象: 是 target 对象的代理对象
    9. public Object getProxyInstance() {
    10. //1. 创建一个工具类
    11. Enhancer enhancer = new Enhancer();
    12. //2. 设置父类
    13. enhancer.setSuperclass(target.getClass());
    14. //3. 设置回调函数
    15. enhancer.setCallback(this);
    16. //4. 创建子类对象,即代理对象
    17. return enhancer.create();
    18. }
    19. //重写 intercept 方法,会调用目标对象的方法
    20. @Override
    21. public Object intercept(Object arg0, Method method, Object[] args, MethodProxy arg3) throws Throwable {
    22. System.out.println("Cglib代理模式 ~~ 开始");
    23. Object returnVal = method.invoke(target, args);
    24. System.out.println("Cglib代理模式 ~~ 提交");
    25. return returnVal;
    26. }
    27. }

    测试

    创建代理对象的性能测试

    使用JMH进行测试

    可以看到创建代理对象时 JDK速度远大于Cglib,这是由于cglib创建对象时需要操作字节码。

    代表的是每秒中jdk可以执行下列方法 1926W 次, 也就是创建代理类 1926W 次。

    1. @Benchmark
    2. public void testJDK() {
    3. ITeacherDao target = new TeacherDao();
    4. ITeacherDao proxyInstance = (ITeacherDao)new ProxyFactory(target).getProxyInstance();
    5. }
    6. @Benchmark
    7. public void testCGLIB() {
    8. TeacherDaoCglib target2 = new TeacherDaoCglib();
    9. TeacherDaoCglib proxyInstance2 = (TeacherDaoCglib)new ProxyFactoryCglib(target2).getProxyInstance();
    10. }

    调用代理对象方法的性能测试

    先测的两组配置参数如下,测试结果两次不一致。

    @BenchmarkMode({Mode.Throughput})
    @Warmup(iterations = 3,time = 3,timeUnit = TimeUnit.SECONDS)
    @Measurement(iterations = 3, time = 5,timeUnit = TimeUnit.SECONDS)

    加大测试的组数和每组时间后,结果显示 JDK执行速度高于Cglib

     

    总结

    Cglib执行速度比JDK快? 不同jdk版本不一样。

    1、cglib底层是ASM字节码生成框架,但是字节码技术生成代理类,在JDL1.6之前比使用java反射的效率要高

    2、在jdk6之后逐步对JDK动态代理进行了优化,在调用次数比较少时效率高于cglib代理效率

    3、只有在大量调用的时候cglib的效率高,但是在1.8的时候JDK的效率已高于cglib

    JDK 1.8  动态代理 JDK > Cglib

  • 相关阅读:
    [LeetCode]剑指 Offer 42. 连续子数组的最大和
    LDGRB-01 用于在边缘处理人工智能的嵌入式硬件
    Spring自动装配Bean
    5分钟实现「视频检索」:基于内容理解,无需任何标签
    autoReg | 自动线性和逻辑回归和生存分析
    Flink-常用算子、自定义函数以及分区策略
    关于gdb调试: 你的问题可能会在这里找到答案
    Java基于微信小程序的校园订餐小程序的研究与实现,附源码
    ZKP6.1 Discrete-log-based Polynomial Commitments (Preliminary)
    Java getResource
  • 原文地址:https://blog.csdn.net/weixin_40757930/article/details/125961520