• 四种动态代理性能比较


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

  • 相关阅读:
    meego API
    linux的文件cache导致写文件消耗大量内存
    系统内存不断消耗 导致系统停滞(表面像死机) 但又找不到内存泄漏点
    C常用的LinuxC语言函数库
    GUI
    java 集合类结构图
    接口到底是个什么玩意
    抽象类到底是个什么玩意
    异常
    IO流
  • 原文地址:https://www.cnblogs.com/bjwylpx/p/3683508.html
Copyright © 2020-2023  润新知