zoukankan      html  css  js  c++  java
  • Java 几种动态代理实现及其性能比较

    原处出之于阿里liangf

    Interface:

    package com.sunchao.jdkdyproxy;
    
    public interface Subject {
    
        void request();
    }

    impl:

    package com.sunchao.jdkdyproxy;
    
    public class RealSubject implements Subject {
        private int count;
        @Override
        public void request() {
            count++;
            //System.out.println("real subject does with the request!");
        }
    
    }

    jdk:

    package com.sunchao.jdkdyproxy;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class ClientProxy {
        
        public static Subject createJdkDynamicProxy(final Object delegate) {
            return (Subject) Proxy.newProxyInstance(Thread.currentThread()
                      .getContextClassLoader(), 
                           new Class<?>[] {Subject.class}, new MyInvocation(delegate));
        }
    
        private static class MyInvocation implements InvocationHandler {
      
            final private Object delegate;
            
            MyInvocation(Object delegate) {
                this.delegate = delegate;
            }
            
            @Override
            public Object invoke(Object proxy, Method method, Object[] args)
                    throws Throwable {
            //    System.out.println("aop before real request!");
            return    method.invoke(delegate, args);
            //    System.out.println("aop after real request!");
                //return null;
            }
        }
        
        public static void main(String args[]) {
            Subject delegate = new RealSubject();
            Subject proxy = createJdkDynamicProxy(delegate);
            proxy.request();
        }
    }

    cglib:

    package com.sunchao.cglibproxy;
    
    import java.lang.reflect.Method;
    
    import com.sunchao.jdkdyproxy.*;
    
    import net.sf.cglib.proxy.Enhancer;
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    
    public class CglibProxy {
        
        public static Subject createCglibDynamicProxy(final Object delegate) {
            Enhancer enhancer = new Enhancer();
            enhancer.setCallback(new CglibInterceptor(delegate));
            enhancer.setInterfaces(new Class<?>[]{Subject.class});
            Subject cglibProxy = (Subject) enhancer.create();
            return cglibProxy;
        }
        
        private static class CglibInterceptor implements MethodInterceptor {
    
            final private Object delegate;
            
            CglibInterceptor(Object delegate) {
                this.delegate =delegate;
            }
            
            @Override
            public Object intercept(Object arg0, Method arg1, Object[] arg2,
                    MethodProxy arg3) throws Throwable {
                //System.out.println("aop before do with the request!");
                return arg1.invoke(delegate, arg2);
            //    System.out.println("aop before do with the request!");
                //return null;
            }
        }
    
        public static void main(String args[]) {
            Subject realSubject = new RealSubject();
            Subject cglibProxy = createCglibDynamicProxy(realSubject);
            cglibProxy.request();
            
        }
    }

    javasist dynamic proxy:

    package com.sunchao.javasistproxy;
    
    import java.lang.reflect.Method;
    
    import com.sunchao.jdkdyproxy.Subject;
    
    import javassist.util.proxy.MethodHandler;
    import javassist.util.proxy.ProxyFactory;
    import javassist.util.proxy.ProxyObject;
    
    public class ClientProxy {
        
        public static Subject createJavasistDynamicProxy(final Subject delegate) 
                              throws Exception {
            
            ProxyFactory factory = new ProxyFactory();
            factory.setInterfaces(new Class<?>[]{com.sunchao.jdkdyproxy.Subject.class});
            Class<?> proxyClass = factory.createClass();
            Subject javasistProxy = (Subject) proxyClass.newInstance();
            ((ProxyObject)javasistProxy).setHandler(new JavasistInterceptor(delegate));
            return javasistProxy;
        }
        
    
         private static class JavasistInterceptor implements MethodHandler {
             final private Object delegate;
             
             JavasistInterceptor(Object delegate) {
                 this.delegate = delegate;
             }
    
            @Override
            public Object invoke(Object arg0, Method arg1, Method arg2,
                    Object[] arg3) throws Throwable {
                //System.out.println("Aop before the real request");
            return    arg1.invoke(delegate, arg3);
            //    System.out.println("Aop after the real request");
            //    return null;
            }
             
         }
    }

    javasist bytecode proxy:

    package com.sunchao.javasistproxy;
    
    import java.lang.reflect.Field;
    
    import javassist.ClassPool;
    import javassist.CtClass;
    import javassist.CtField;
    import javassist.CtNewConstructor;
    import javassist.CtNewMethod;
    import com.sunchao.jdkdyproxy.RealSubject;
    import com.sunchao.jdkdyproxy.Subject;
    
    public class ByteCodeProxy {
        
        public static Subject createJavasistBytecodeDynamicProxy(final Subject delegate) throws Exception {
            ClassPool pool = ClassPool.getDefault();
            CtClass proxyClass = pool.makeClass(Subject.class.getName() + "JavasistProxy");
            proxyClass.addInterface(pool.get(Subject.class.getName()));
            proxyClass.addConstructor(CtNewConstructor.defaultConstructor(proxyClass));
            proxyClass.addField(CtField.make("private " + Subject.class.getName() + " delegate ;", proxyClass));
            proxyClass.addMethod(CtNewMethod.make(
                    "public void request() { delegate.request();}", proxyClass));
            Class<?> clazz = proxyClass.toClass();
            Subject bytecodeProxy = (Subject) clazz.newInstance();
            Field field = bytecodeProxy.getClass().getDeclaredField("delegate");
            field.setAccessible(true);
            field.set(bytecodeProxy,delegate);
            return bytecodeProxy;
        }
        
        public static void main(String args[]) throws Exception {
            Subject delegate = new RealSubject();
            Subject bytecodeProxy = createJavasistBytecodeDynamicProxy(delegate);
            bytecodeProxy.request();
        }
    
    }

    asm:

    package com.sunchao.asm;
    
    import java.lang.reflect.Field;
    import java.nio.ReadOnlyBufferException;
    
    import org.objectweb.asm.ClassWriter;
    import org.objectweb.asm.FieldVisitor;
    import org.objectweb.asm.MethodVisitor;
    import org.objectweb.asm.Opcodes;
    
    import com.sunchao.jdkdyproxy.RealSubject;
    import com.sunchao.jdkdyproxy.Subject;
    
    public class ASMProxy {
    
        public static Subject createAsmByteCodeDynamicProxy(Subject delegate) throws Exception {
            ClassWriter classWriter = new ClassWriter(true);
            String className = Subject.class.getName() + "AsmProxy";
            String classPath = className.replace('.', '/');
            String interfacePath = Subject.class.getName().replace('.', '/');
            
            classWriter.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC, classPath, null,
                    "java/lang/Object", new String[] {interfacePath});
            MethodVisitor initVistor = (MethodVisitor) classWriter.visitMethod(Opcodes.ACC_PUBLIC,
                    "<init>", "()V", null, null);
            initVistor.visitCode();
            initVistor.visitVarInsn(Opcodes.ALOAD, 0);
            initVistor.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
            initVistor.visitInsn(Opcodes.RETURN);
            initVistor.visitMaxs(0, 0);
            initVistor.visitEnd();
            
            
            FieldVisitor fieldVisitor = classWriter.visitField(Opcodes.ACC_PRIVATE, "delegate" ,
                    "L" + interfacePath + ";" , null, null);
            fieldVisitor.visitEnd();
            
            MethodVisitor methodVisitor = classWriter.visitMethod(Opcodes.ACC_PUBLIC, "request", "()V", null, null);
            methodVisitor.visitCode();
            methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
            methodVisitor.visitFieldInsn(Opcodes.GETFIELD, classPath, "delegate", "L" + interfacePath + ";");
            methodVisitor.visitMethodInsn(Opcodes.INVOKEINTERFACE, interfacePath, "request", "()V");
            methodVisitor.visitInsn(Opcodes.RETURN);
            methodVisitor.visitMaxs(0, 0);
            methodVisitor.visitEnd();    
            
            classWriter.visitEnd();
            byte[] code = classWriter.toByteArray();
            Subject asmProxy = (Subject) new ByteArrayClassLoader().getClass(className, code).newInstance();
            Field field  = asmProxy.getClass().getDeclaredField("delegate");
            field.setAccessible(true);
            field.set(asmProxy, delegate);
            return asmProxy;
            
        }
        private static class ByteArrayClassLoader extends ClassLoader {
            
            ByteArrayClassLoader() {
                super(ByteArrayClassLoader.getSystemClassLoader());
            }
            
            public synchronized Class<?> getClass(String name, byte[] code) {
                if(name == null)
                    throw new IllegalArgumentException("name == null");
                return defineClass(name, code, 0, code.length);
            }    
        }
        
        public static void main(String args[]) throws Exception{
            Subject real = new RealSubject();
            Subject asmProxy  =createAsmByteCodeDynamicProxy(real);
            asmProxy.request();
        }
    }

    四种比较:

    package com.sunchao.reflecttest;
    
    import java.text.DecimalFormat;
    
    import com.sunchao.asm.ASMProxy;
    import com.sunchao.cglibproxy.CglibProxy;
    import com.sunchao.javasistproxy.ByteCodeProxy;
    import com.sunchao.jdkdyproxy.ClientProxy;
    import com.sunchao.jdkdyproxy.RealSubject;
    import com.sunchao.jdkdyproxy.Subject;
    /**
     * 
     * @author Administrator
     *
     */
    public class DynamicProxyTest {
        
        public static void main(String args[]) throws Exception {
            Subject delegate = new RealSubject();
            long time = System.currentTimeMillis();
            Subject jdkProxy = ClientProxy.createJdkDynamicProxy(delegate);
            time = System.currentTimeMillis() - time;
            System.out.println("create jdk dynamic proxy : " + time + " ms");
            
            time = System.currentTimeMillis();
            Subject cglibProxy = CglibProxy.createCglibDynamicProxy(delegate);
            time = System.currentTimeMillis() - time;
            System.out.println("create cglib dynamic proxy : " + time + " ms");
            
            time = System.currentTimeMillis();
            Subject javasistProxy = com.sunchao.javasistproxy.ClientProxy.createJavasistDynamicProxy(delegate);
            time = System.currentTimeMillis() - time;
            System.out.println("create javasist dynamic proxy : " + time + " ms");
            
            time = System.currentTimeMillis();
            Subject javasistbytecodeProxy = ByteCodeProxy.createJavasistBytecodeDynamicProxy(delegate);
            time = System.currentTimeMillis() - time;
            System.out.println("create javasist bytecode proxy : "  + time + " ms" );
            
            time = System.currentTimeMillis();
            Subject asmProxy = ASMProxy.createAsmByteCodeDynamicProxy(delegate);
            time = System.currentTimeMillis() - time;
            System.out.println("create asm bytecode proxy : " + time + " ms");
            System.out.println("<============================================>");
            for(int i = 0; i < 3; i++){
                test(jdkProxy, "run the jdkDynamicProxy : ");
                test(cglibProxy, "run the cglibDynamicProxy : ");
                test(javasistProxy, "run the javasistProxy : ");
                test(javasistbytecodeProxy, "run the javasist byte code proxy : ");
                test(asmProxy, "run the asm byte code proxy : ");
                System.out.println("<-------------------------------------->");
            }
            
        }
        
        public static void test(Subject delegate, String label) {
            delegate.request();//warm up
            int count = 10000000;
            long time = System.currentTimeMillis();
            for(int i = 0; i < count; i++){
                delegate.request();
            }
            time = System.currentTimeMillis() - time;
            System.out.println(label + time + " ms, " + new DecimalFormat().format(count * 1000 / time) + " t/s");
        }
    
    }

    四种比较结果:

    create jdk dynamic proxy : 9 ms
    create cglib dynamic proxy : 169 ms
    create javasist dynamic proxy : 109 ms
    create javasist bytecode proxy : 375 ms
    create asm bytecode proxy : 9 ms
    <============================================>
    run the jdkDynamicProxy : 864 ms, 1,632,020 t/s
    run the cglibDynamicProxy : 794 ms, 1,775,901 t/s
    run the javasistProxy : 816 ms, 1,728,021 t/s
    run the javasist byte code proxy : 80 ms, 17,625,817 t/s
    run the asm byte code proxy : 76 ms, 18,553,492 t/s
    <-------------------------------------->
    run the jdkDynamicProxy : 707 ms, 1,994,434 t/s
    run the cglibDynamicProxy : 713 ms, 1,977,651 t/s
    run the javasistProxy : 862 ms, 1,635,806 t/s
    run the javasist byte code proxy : 66 ms, 21,364,627 t/s
    run the asm byte code proxy : 73 ms, 19,315,964 t/s
    <-------------------------------------->
    run the jdkDynamicProxy : 740 ms, 1,905,493 t/s
    run the cglibDynamicProxy : 693 ms, 2,034,726 t/s
    run the javasistProxy : 844 ms, 1,670,693 t/s
    run the javasist byte code proxy : 74 ms, 19,054,937 t/s
    run the asm byte code proxy : 83 ms, 16,988,739 t/s
    <-------------------------------------->

    四种各种调用10000000次:

    从创建动态代理类的时间可以看出:jdk和asm效果最优,javasist bytecode次之,在其次cglib,最差的是javasist dynamic proxy
    从代理调用的时间可以看出:asm和javasist差不多最好,其他三个差不多,差距较大;
    asm比较底层,对虚拟机指令要求高,综合javasist bytecode性能综合比较好,
  • 相关阅读:
    aaronyang的百度地图API之LBS云与.NET开发 Javascript API 2.0【把数据存到LBS云2/2】
    aaronyang的百度地图API之LBS云与.NET开发 Javascript API 2.0【把数据存到LBS云1/2】
    aaronyang的百度地图API之LBS云与.NET开发 Javascript API 2.0【基本地图的操作】
    aaronyang的百度地图API之LBS云 笔记[位置数据 geotable]
    aaronyang的百度地图API之LBS云 笔记[开发准备]
    windows7 sqlserver2012 无法写入受保护的内存 解决办法
    [AaronYang风格]微软Unity2.X系统学习笔记,记录
    Javascript 原生Cookie使用用法
    注册asp.net 4.0 到iis
    茗洋Easy UI 1.3.5 部分问题解决系列专题[自定义alert关闭时间,自动关]
  • 原文地址:https://www.cnblogs.com/onlysun/p/4528986.html
Copyright © 2011-2022 走看看