四種動態代理性能比較


本示例演示了采用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();
    }
}
View Code

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;
    }
}
View Code

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();
    }
}
View Code

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;
    }
View Code

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();
    }
View Code

性能對比:

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);
    }
View Code

性能輸出:
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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM