• 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

  • 相关阅读:
    【ML】第五章 支持向量机
    springboot+二手车交易系统 毕业设计-附源码131456
    仿IOS 对话框和底部弹出框
    网络管理器(NetworkManager)未运行。 这个问题如何解决
    MATLAB算法实战应用案例精讲-【图像处理】图像识别分类
    VMware ESXI & vCenter 开启 SNMP 方法:
    干货丨数据仓库工具hive面试题集锦
    【MindSpore】DCGAN生成漫画头像-----利用华为云modelarts云终端实现
    接口压力测试 jmeter--进阶篇(三)
    CFdiv2-Common Number-(奇偶数二分+规律)
  • 原文地址:https://blog.csdn.net/weixin_40757930/article/details/125961520