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性能综合比较好,
时间: 2024-10-13 22:53:20

Java 几种动态代理实现及其性能比较的相关文章

Java中两种动态代理的实现

本文介绍了java中两种动态代理的实现方法,Spring的动态代理也是基于这两种方法的.直接附上源码: 1.JDK实现 使用JDK实现动态代理必须使用接口 接口Work.java public interface Work { public void work(); } 实现类WorkImpl.java public class WorkImpl implements Work { @Override public void work() { System.out.println("我在工作&q

使用Java中的动态代理实现数据库连接池

2002 年 12 月 05 日 作者通过使用JAVA中的动态代理实现数据库连接池,使使用者可以以普通的jdbc连接的使用习惯来使用连接池. 数据库连接池在编写应用服务是经常需要用到的模块,太过频繁的连接数据库对服务性能来讲是一个瓶颈,使用缓冲池技术可以来消除这个瓶颈.我们可以在 互联网上找到很多关于数据库连接池的源程序,但是都发现这样一个共同的问题:这些连接池的实现方法都不同程度地增加了与使用者之间的耦合度.很多的连接池 都要求用户通过其规定的方法获取数据库的连接,这一点我们可以理解,毕竟目前

java反射与动态代理

Java反射与动态代理 Java反射机制可以动态地获取类的结构,动态地调用对象的方法,是java语言一个动态化的机制.java动态代理可以在不改变被调用对象源码的前提下,在被调用方法前后增加自己的操作,极大地降低了模块之间的耦合性.这些都是java的基础知识,要想成为一名合格的程序猿,必须掌握! Java反射机制 JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为

十分钟理解Java中的动态代理

十分钟帮助大家理解Java中的动态代理,什么是动态代理?感兴趣的小伙伴们可以参考一下 若代理类在程序运行前就已经存在,那么这种代理方式被成为 静态代理 ,这种情况下的代理类通常都是我们在Java代码中定义的. 通常情况下, 静态代理中的代理类和委托类会实现同一接口或是派生自相同的父类. 一.概述1. 什么是代理我们大家都知道微商代理,简单地说就是代替厂家卖商品,厂家"委托"代理为其销售商品.关于微商代理,首先我们从他们那里买东西时通常不知道背后的厂家究竟是谁,也就是说,"委托

java中的动态代理(二)

上一节我介绍了什么是静态代理.在静态代理中的代理对象是直接定义在代码中的,这样会导致代码不能复用并且工作量也会成倍的增加所以在日常的开发中我们更多使用的是动态代理模式.在动态代理中,代理类在是程序运行中动态生成的,在java中一般有两种方式来实现动态代理模式,它们分别是javaSDK动态代理和第三方类库cglib动态代理. 今天我介绍的是java SDK动态代理.首先我们先来看一下如何使用java SDK实现动态代理模式: public class JavaSDKProxyTest { stat

java中的动态代理机制

在java的动态代理机制中,有两个重要的类或接口,一个是 InvocationHandler(Interface).另一个则是 Proxy(Class),这一个类和接口是实现我们动态代理所必须用到的.下面通过代码来学习java中的动态代理技术. 首先定义一个接口: package com.aop.spring; /** * Created by xinfengyao on 16-2-29. */ public interface Perform { public void play(); } 实

深入解析Java设计模式之动态代理

深入解析Java设计模式之动态代理 代理是基本的设计模式之一,它是你为了提供额外的或不同的操作,而插入的用来代替"实际"对象的对象.这些操作通常涉及与"实际"对象的通信,因此代理通常充当着中间人的角色,下面是一个用来展示动态代理结构的简单示例: /** 普通(非动态)代理示例: */ interface Interface { void doSomething(); void somethingElse(String arg); } class RealObject

Java学习笔记——动态代理

所谓动态,也就是说这个东西是可变的,或者说不是一生下来就有的.提到动态就不得不说静态,静态代理,个人觉得是指一个代理在程序中是事先写好的,不能变的,就像上一篇"Java学习笔记--RMI"中的远程代理,其中客户端服务对象就是一个远程服务对象的代理,这个代理可以使得客户在操作时感觉像在操作本地对象一样,远程对象对于客户是透明的.我们可以看出这里的远程代理,是在程序中事先写好的,而本节我们要讨论的远程代理,是由JVM根据反射机制,在程序运行时动态生成的.(以上是本人的理解,如果有不正确的地

浅谈-Java设计模式之动态代理

动态代理模式(Dynamic Proxy Pattern): 在java的动态代理机制中,有两个重要的类或接口,一个是 InvocationHandler(Interface).另一个则是 Proxy(Class),这一个类和接口是实现我们动态代理所必须用到的. 首先我们先来看看java的API帮助文档是怎么样对这两个类进行描述的: InvocationHandler该接口唯一方法 invoke(Object proxy, Method method, Object[] args) Object