本示例演示了采用JDK動態代理,CGLIB庫的動態代理、Javassist庫的動態代理及Javassist動態字節碼生成代理四種動態代理的生成方法,並對這四種動態代理的對象創建及方法調用的性能進行了對比。測試結果表時:
1, JDK動態代理和CGLIB,Javassist動態字節碼生成的動態代理,對方法調用的方面的性能相差不是很大。在這三者中Javassist動態字節碼方式性能最好,可以達前二種方式的二倍以上。三者性能為: Javassist動態字節碼>JDK動態代理>CGLIB動態代理。
2,采用Javassist工廠生成的動態代理在方法的調用上性能明顯比JDK動態代理、CGLIB動態代理及Javassist動態字節碼三者差,大約是后三者性能的二分之一。
3,無論何種方式實現的動態代理其性能都無法與普通代理的性能相比,並且有二個數量級的差距。
普通代理的實現:

/** * 代理類 * @author LPX * */ public class DBQueryProxy implements IDBQuery { private IDBQuery real=null; /* (non-Javadoc) * @see Pattern.DynamicProxy.IDBQuery#request() */ @Override public void request() { if(real==null){ real=new DBQuery(); } //調用被代理的對象 real.request(); } }
JDK動態代理實現:

/** * 采用JDK的動態代理處理器 * @author LPX * */ class JDKDynamicProxyHandler implements InvocationHandler{ private IDBQuery proxied=null; /** * 創建動態代理處理對象 * @param proxied */ public JDKDynamicProxyHandler(IDBQuery proxied){ this.proxied=proxied; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //調用被代理的對象的方法 return method.invoke(proxied, args); } } /** * JDK動態代理 * @author LPX * */ public class JDKDynamicProxy { public static IDBQuery createDynamicProxy(){ IDBQuery proxy=(IDBQuery)Proxy.newProxyInstance(IDBQuery.class.getClassLoader(), new Class[]{IDBQuery.class}, new JDKDynamicProxyHandler(new DBQuery())); return proxy; } }
CGLIB動態代理實現:

/** * 采用CGLIB庫創建的動態代理 */ package Pattern.DynamicProxy; import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; /** * 方法執行的攔截器 * @author LPX * */ class ProxyMethodInterceptor implements MethodInterceptor{ private IDBQuery proxied=null; public ProxyMethodInterceptor(IDBQuery proxied){ this.proxied=proxied; } @Override public Object intercept(Object arg0, Method method, Object[] arg2, MethodProxy arg3) throws Throwable { //方法攔截 return method.invoke(proxied, arg2); } } /** * CGLIB動態代理 * @author LPX * */ public class CglibDynamicProxy { public static IDBQuery createDynamicProxy(){ Enhancer enhancer=new Enhancer(); //設置方法攔截器 enhancer.setCallback(new ProxyMethodInterceptor(new DBQuery())); //設置要實現的接口列表 enhancer.setInterfaces(new Class[]{IDBQuery.class}); //產生動態代理對象 return (IDBQuery)enhancer.create(); } }
Javassist庫動態代理實現:

/** * Javassist庫實現的動態代理 * @return */ private static IDBQuery createJavassistProxy() { ProxyFactory factory=new ProxyFactory(); factory.setInterfaces(new Class[]{IDBQuery.class}); IDBQuery proxy=null; class ProxyMethodHandler implements MethodHandler{ private IDBQuery proxied=null; public ProxyMethodHandler(IDBQuery proxied){ this.proxied=proxied; } @Override public Object invoke(Object arg0, Method method, Method arg2, Object[] arg3) throws Throwable { //System.out.println("Javassist Method Handler invoke."); return method.invoke(proxied, arg3); } } factory.setHandler(new ProxyMethodHandler(new DBQuery())); try{ proxy=(IDBQuery)factory.create(null, null); }catch(Exception e){ e.printStackTrace(); } return proxy; }
Javassist庫動態字節碼代理實現:

/** * 使用Javassist動態代碼實現的代理 * @return */ private static IDBQuery createJavassistBytecodeProxy() throws Throwable{ ClassPool pool=ClassPool.getDefault(); //創建一個類 CtClass ctclass=pool.makeClass(IDBQuery.class.getName()+"_javassistbytecode_proxy"); //添加要實現的接口 ctclass.addInterface(pool.get(IDBQuery.class.getName())); ctclass.addConstructor(CtNewConstructor.defaultConstructor(ctclass)); //添加域 ctclass.addField(CtField.make("public "+IDBQuery.class.getName()+" real;", ctclass)); //添加方法 ctclass.addMethod(CtNewMethod.make("public void request(){ if (real==null){ real=new " +DBQuery.class.getName()+"();} return real.request();}", ctclass)); Class pc=ctclass.toClass(); return (IDBQuery)pc.newInstance(); }
性能對比:

private static void Tuning(int type) throws Throwable{ IDBQuery proxy=null; long start=System.currentTimeMillis(); String typeName=""; switch(type){ case 1: proxy=new DBQueryProxy(); typeName="Proxy"; break; case 2: proxy=JDKDynamicProxy.createDynamicProxy(); typeName="JDKProxy"; break; case 3: proxy=CglibDynamicProxy.createDynamicProxy(); typeName="CglibProxy"; break; case 4: proxy=createJavassistProxy(); typeName="JavassistProxy"; break; case 5: proxy=createJavassistBytecodeProxy(); typeName="JavassistProxy"; break; } long end=System.currentTimeMillis(); System.out.println(typeName+" created: "+(end-start)); System.out.println(proxy.getClass().getName()); start=end; //執行3千萬次,看看執行的時間是多少 for(int i=0;i<30000000;i++) proxy.request(); end=System.currentTimeMillis(); System.out.println("Call "+typeName+" request(): "+(end-start)); System.out.println(""); } /** * @param args */ public static void main(String[] args) throws Throwable { Tuning(1); Tuning(2); Tuning(3); Tuning(4); Tuning(5); }
性能輸出:
Proxy created: 0
Pattern.DynamicProxy.DBQueryProxy
Call Proxy request(): 4
JDKProxy created: 4
$Proxy0
Call JDKProxy request(): 190
CglibProxy created: 50
Pattern.DynamicProxy.IDBQuery$$EnhancerByCGLIB$$b069fedf
Call CglibProxy request(): 227
JavassistProxy created: 21
Pattern.DynamicProxy.IDBQuery_$$_javassist_0
Call JavassistProxy request(): 407
JavassistProxy created: 35
Pattern.DynamicProxy.IDBQuery_javassistbytecode_proxy
Call JavassistProxy request(): 83