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

导读:本篇文章讲解 2种动态代理方式的性能测试(JDK1.8 JDK > Cglib),希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

目录

动态代理

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方法去执行

public class ProxyHost implements InvocationHandler {

    private Object target;
	// 注入一个实现类  
    public void setTarget(Object target) {
        this.target = target;
    }
	// 根据实现类  拿到其实现的方法
    public Object getProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),
                target.getClass().getInterfaces(),this);
    }
    // 在使用时直接调用方法即可  
    // 调用时就会通过 invoke来实现
    @Override
    public Object invoke(Object proxy,Method method,Object[] args) throws Throwable {
        System.out.println("调用方法前的日志");// 在调用原对象的方法时  可以增强
        Object result = method.invoke(target,args);
        System.out.println("调用方法后的日志");
        return result;
    }

}

cglib动态代理

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

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


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

}

测试

创建代理对象的性能测试

使用JMH进行测试

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

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

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

   @Benchmark
    public void testJDK() {
        ITeacherDao target = new TeacherDao();
        ITeacherDao proxyInstance = (ITeacherDao)new ProxyFactory(target).getProxyInstance();
    }

    @Benchmark
    public void testCGLIB() {
            TeacherDaoCglib target2 = new TeacherDaoCglib();
            TeacherDaoCglib proxyInstance2 = (TeacherDaoCglib)new ProxyFactoryCglib(target2).getProxyInstance();
    }

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

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

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

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

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

 2种动态代理方式的性能测试(JDK1.8 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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/92789.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!