Java中自带的动态代理的类必须要实现一个接口,而且据说使用反射的效率也并不是很高。于是CGLIB就诞生了。
使用CGLib实现动态代理,完全不受代理类必须实现接口的限制,而且CGLib底层采用ASM字节码生成框架,使用字节码技术生成代理类,理论上比使用Java反射效率要高。
那么我们测试下,这个运行的效率如何。
1、 测试的准备情况
准备1:好记性不如烂笔头46-java拦截器-彻底理解动态代理的概念(1) http://blog.csdn.net/ffm83/article/details/43699619
准备2: 好记性不如烂笔头47-java拦截器-用CGLib实现动态代理(2)
http://blog.csdn.net/ffm83/article/details/43702321
为了测试结果方便观察,把所有的打印输出关闭。
JDK版本: jdk1.6.0_25
2、 测试运行效率的源代码
package com.tools;
import com.CGLib.WangBaoQiang;
import com.proxy.Actor;
/**
* 使用预热模式
* JVM参数:-XX:PrintCompilation
* @author 范芳铭
*/
public class BaseRun_Proxy_Test {
public static void main(String[] args) throws Exception{
int warmUpCycles = 1000000; //预热次数
BaseRun_Proxy_Test se = new BaseRun_Proxy_Test();
System.out.println("预热循环开始 ...");
se.runTest(warmUpCycles);
System.out.println("预热结束");
Thread.sleep(1000); //让系统暂停
System.out.println("进入正式循环 ...");
se.runTest(1);
se.runTest(100);
se.runTest(10000);
se.runTest(1000000);
se.runTest(20000000); //2000千万次,我们系统一天的访问量
System.out.println("正式运算完成");
}
private void runTest(int iterations){
BaseRun_Proxy_Test lot = new BaseRun_Proxy_Test();
//运行JAVA自带动态代理
long startTime = System.nanoTime();
for(int i = 0 ; i < iterations ; i ++){
lot.getJavaProxyLoop();
}
long elapsedTime = System.nanoTime();
System.out.println("运行JAVA自带动态代理:" + iterations + ",结束,耗时:" + (elapsedTime-startTime));
//运行CGLIB
long cglibStartTime = System.nanoTime();
for(int i = 0 ; i < iterations ; i ++){
lot.getCGLibLoop();
}
long cglibElapsedTime = System.nanoTime();
System.out.println("运行CGLIB动态代理:" + iterations + ",结束,耗时:" + (cglibElapsedTime-cglibStartTime));
}
public void getJavaProxyLoop(){
// 首先找到经纪人
com.proxy.ActorJingJiRen proxy = new com.proxy.ActorJingJiRen();
// 通过经纪人获得相关演员(代理对象)
Actor p = proxy.getProxy();
String retValue = p.sing("天下无贼");
String value = p.dance("凤凰传奇");
}
public void getCGLibLoop(){
com.CGLib.ActorJingJiRen proxy = new com.CGLib.ActorJingJiRen();
// 通过经纪人获得相关演员(代理对象)
WangBaoQiang p = proxy.getProxy();
String retValue = p.sing("天下无贼");
String value = p.dance("凤凰传奇");
}
}
3、 运行结果
预热循环开始 …
运行JAVA自带动态代理:1000000,结束,耗时:2390557348
运行CGLIB动态代理:1000000,结束,耗时:6111703990
预热结束
进入正式循环 …
运行JAVA自带动态代理:1,结束,耗时:35715
运行CGLIB动态代理:1,结束,耗时:39409
运行JAVA自带动态代理:100,结束,耗时:381782
运行CGLIB动态代理:100,结束,耗时:1162997
运行JAVA自带动态代理:10000,结束,耗时:23943050
运行CGLIB动态代理:10000,结束,耗时:58153974
运行JAVA自带动态代理:1000000,结束,耗时:2403822826
运行CGLIB动态代理:1000000,结束,耗时:5804202226
运行JAVA自带动态代理:20000000,结束,耗时:48913882774
运行CGLIB动态代理:20000000,结束,耗时:118967606438
正式运算完成
4、 运行效率的表格
CGlib的动态代理的效率,看起来比JAVA自带的效率要低。这个和我们所听到的情况可能不一样。
5、 其他
将CGLIB放在java自带proxy的方法之前,数据情况和上面基本一致。