四种动态代理性能比较

本示例演示了采用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

原文地址:https://www.cnblogs.com/bjwylpx/p/3683508.html