`

动态代理对象

    博客分类:
  • java
阅读更多

之前研究了一下dubbo的源码,rpc服务框架里面非常重要的一部分时动态代理,无论时服务端的对象或是消费端的对象,都是通过代理来处理的。

代理在我们很多框架,中间件甚至业务开发场景中都是非常重要的技术。

dubbo使用了jdk原生的动态代理和javassist的字节码代理

 

下面的代码也是转了dubbo作者的博客,深入的学习了下。

不单是学习了技术的方案,同时也学习了考虑事情的思路。当有很多备选的技术方案是,最实际的就是拉出来做对比,再选型。

 

package com.test.proxy.proxy_demo;


import java.lang.reflect.Field;  
import java.lang.reflect.InvocationHandler;  
import java.lang.reflect.Method;  
import java.lang.reflect.Proxy;  
import java.text.DecimalFormat;  
  
import javassist.ClassPool;  
import javassist.CtClass;  
import javassist.CtField;  
import javassist.CtNewConstructor;  
import javassist.CtNewMethod;  
import javassist.util.proxy.MethodHandler;  
import javassist.util.proxy.ProxyFactory;  
import javassist.util.proxy.ProxyObject;  
import net.sf.cglib.proxy.Enhancer;  
import net.sf.cglib.proxy.MethodInterceptor;  
import net.sf.cglib.proxy.MethodProxy;  
  
import org.objectweb.asm.ClassWriter;  
import org.objectweb.asm.FieldVisitor;  
import org.objectweb.asm.MethodVisitor;  
import org.objectweb.asm.Opcodes; 

public class DynamicProxyPerformanceTest {

  public static void main(String[] args) throws Exception {  
    CountService delegate = new CountServiceImpl();  
      
    long time = System.currentTimeMillis();  
    CountService jdkProxy = createJdkDynamicProxy(delegate);  
    time = System.currentTimeMillis() - time;  
    System.out.println("Create JDK Proxy: " + time + " ms");  
      
    time = System.currentTimeMillis();  
    CountService cglibProxy = createCglibDynamicProxy(delegate);  
    time = System.currentTimeMillis() - time;  
    System.out.println("Create CGLIB Proxy: " + time + " ms");  
      
    time = System.currentTimeMillis();  
    CountService javassistProxy = createJavassistDynamicProxy(delegate);  
    time = System.currentTimeMillis() - time;  
    System.out.println("Create JAVAASSIST Proxy: " + time + " ms");  
      
    time = System.currentTimeMillis();  
    CountService javassistBytecodeProxy = createJavassistBytecodeDynamicProxy(delegate);  
    time = System.currentTimeMillis() - time;  
    System.out.println("Create JAVAASSIST Bytecode Proxy: " + time + " ms");  
      
    time = System.currentTimeMillis();  
    CountService asmBytecodeProxy = createAsmBytecodeDynamicProxy(delegate);  
    time = System.currentTimeMillis() - time;  
    System.out.println("Create ASM Proxy: " + time + " ms");  
    System.out.println("================");  
      
    for (int i = 0; i < 3; i++) {  
        test(jdkProxy, "Run JDK Proxy: ");  
        test(cglibProxy, "Run CGLIB Proxy: ");  
        test(javassistProxy, "Run JAVAASSIST Proxy: ");  
        test(javassistBytecodeProxy, "Run JAVAASSIST Bytecode Proxy: ");  
        test(asmBytecodeProxy, "Run ASM Bytecode Proxy: ");  
        System.out.println("----------------");  
    }  
}  

private static void test(CountService service, String label)  
        throws Exception {  
    service.count(); // warm up  
    int count = 10000000;  
    long time = System.currentTimeMillis();  
    for (int i = 0; i < count; i++) {  
        service.count();  
    }  
    time = System.currentTimeMillis() - time;  
    System.out.println(label + time + " ms, " + new DecimalFormat().format(count * 1000 / time) + " t/s");  
}  

//JDK代理对象
private static CountService createJdkDynamicProxy(final CountService delegate) {  
    CountService jdkProxy = (CountService) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),  
            new Class[] { CountService.class }, new JdkHandler(delegate));  
    return jdkProxy;  
}  
  
private static class JdkHandler implements InvocationHandler {  

    final Object delegate;  

    JdkHandler(Object delegate) {  
        this.delegate = delegate;  
    }  

    public Object invoke(Object object, Method method, Object[] objects)  
            throws Throwable {  
        return method.invoke(delegate, objects);  
    }  
} 

//CGLIB代理对象
private static CountService createCglibDynamicProxy(final CountService delegate) throws Exception {  
    Enhancer enhancer = new Enhancer();  
    enhancer.setCallback(new CglibInterceptor(delegate));  
    enhancer.setInterfaces(new Class[] { CountService.class });  
    CountService cglibProxy = (CountService) enhancer.create();  
    return cglibProxy;  
}  

private static class CglibInterceptor implements MethodInterceptor {  
      
    final Object delegate;  

    CglibInterceptor(Object delegate) {  
        this.delegate = delegate;  
    }  

    public Object intercept(Object object, Method method, Object[] objects,  
            MethodProxy methodProxy) throws Throwable {  
        return methodProxy.invoke(delegate, objects);  
    }  
}  

//JAVASSIST代理对象
private static CountService createJavassistDynamicProxy(final CountService delegate) throws Exception {  
    ProxyFactory proxyFactory = new ProxyFactory();  
    proxyFactory.setInterfaces(new Class[] { CountService.class });  
    Class<?> proxyClass = proxyFactory.createClass();  
    CountService javassistProxy = (CountService) proxyClass.newInstance();  
    ((ProxyObject) javassistProxy).setHandler(new JavaAssitInterceptor(delegate));  
    return javassistProxy;  
}  

private static class JavaAssitInterceptor implements MethodHandler {  

    final Object delegate;  

    JavaAssitInterceptor(Object delegate) {  
        this.delegate = delegate;  
    }  

    public Object invoke(Object self, Method m, Method proceed,  
            Object[] args) throws Throwable {  
        return m.invoke(delegate, args);  
    }  
}  

//JAVASSIST字节码代理对象
private static CountService createJavassistBytecodeDynamicProxy(CountService delegate) throws Exception {  
    ClassPool mPool = new ClassPool(true);  
    CtClass mCtc = mPool.makeClass(CountService.class.getName() + "JavaassistProxy");  
    mCtc.addInterface(mPool.get(CountService.class.getName()));  
    mCtc.addConstructor(CtNewConstructor.defaultConstructor(mCtc));  
    mCtc.addField(CtField.make("public " + CountService.class.getName() + " delegate;", mCtc));  
    mCtc.addMethod(CtNewMethod.make("public int count() { return delegate.count(); }", mCtc));  
    Class<?> pc = mCtc.toClass();  
    CountService bytecodeProxy = (CountService) pc.newInstance();  
    Field filed = bytecodeProxy.getClass().getField("delegate");  
    filed.set(bytecodeProxy, delegate);  
    return bytecodeProxy;  
}  
 
//asm字节码代理对象
private static CountService createAsmBytecodeDynamicProxy(CountService delegate) throws Exception {  
    ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);  
    String className = CountService.class.getName() +  "AsmProxy";  
    String classPath = className.replace('.', '/');  
    String interfacePath = CountService.class.getName().replace('.', '/');  
    classWriter.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC, classPath, null, "java/lang/Object", new String[] {interfacePath});  
    
    //ACC_PUBLIC <init> ()V表示是一个公共方法,没有参数,返回值类型是“v”void <init>表示是构造函数
    MethodVisitor initVisitor = classWriter.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);  
    initVisitor.visitCode();  
    initVisitor.visitVarInsn(Opcodes.ALOAD, 0);  
    initVisitor.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V");  
    initVisitor.visitInsn(Opcodes.RETURN);  
    initVisitor.visitMaxs(0, 0);  
    initVisitor.visitEnd();  
      
    FieldVisitor fieldVisitor = classWriter.visitField(Opcodes.ACC_PUBLIC, "delegate", "L" + interfacePath + ";", null, null);  
    fieldVisitor.visitEnd();  
      
    MethodVisitor methodVisitor = classWriter.visitMethod(Opcodes.ACC_PUBLIC, "count", "()I", null, null);  
    methodVisitor.visitCode();  
    methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);  
    methodVisitor.visitFieldInsn(Opcodes.GETFIELD, classPath, "delegate", "L" + interfacePath + ";");  
    methodVisitor.visitMethodInsn(Opcodes.INVOKEINTERFACE, interfacePath, "count", "()I");  
    methodVisitor.visitInsn(Opcodes.IRETURN);  
    methodVisitor.visitMaxs(0, 0);  
    methodVisitor.visitEnd();  
      
    classWriter.visitEnd();  
    byte[] code = classWriter.toByteArray();  
    CountService bytecodeProxy = (CountService) new ByteArrayClassLoader().getClass(className, code).newInstance();  
    Field filed = bytecodeProxy.getClass().getField("delegate");  
    filed.set(bytecodeProxy, delegate);  
    return bytecodeProxy;  
}  
  

private static class ByteArrayClassLoader extends ClassLoader {  

    public ByteArrayClassLoader() {  
        super(ByteArrayClassLoader.class.getClassLoader());  
    }  

    public synchronized Class<?> getClass(String name, byte[] code) {  
        if (name == null) {  
            throw new IllegalArgumentException("");  
        }  
        return defineClass(name, code, 0, code.length);  
    }  

}  
}

 

 

 

 

package com.test.proxy.proxy_demo;

public interface CountService {

  int count();
}

 

 

 

package com.test.proxy.proxy_demo;

public class CountServiceImpl implements CountService{

  private int count = 0;  
  @Override
  public int count() {
    return count ++;
  }

}

 

分享到:
评论

相关推荐

    JDK动态代理_JDK动态代理

    3. **创建动态代理对象**:使用`Proxy.newProxyInstance`方法创建动态代理对象,传入ClassLoader、接口数组和上一步骤创建的InvocationHandler实例。 4. **调用代理对象的方法**:当调用代理对象的方法时,会自动...

    Jdk动态代理和cglib动态代理原理

    2. **Proxy类**:用于创建动态代理对象,通过`newProxyInstance()`静态方法,传入类加载器、接口数组和InvocationHandler实例来生成代理对象。 3. **实现过程**:首先,你需要定义一个接口,然后创建实现该接口的...

    java动态代理demo

    `java.lang.reflect.Proxy` 类是用于创建动态代理对象的工厂类。我们需要使用`Proxy.newProxyInstance()`方法,传入类加载器、接口数组以及自定义的`InvocationHandler`实例,来生成代理对象。 5. **动态代理示例*...

    11 动态代理的例子

    Proxy类提供了创建动态代理对象的方法,而InvocationHandler接口定义了处理代理对象方法调用的逻辑。 1. **InvocationHandler接口**: 这个接口只有一个方法`invoke(Object proxy, Method method, Object[] args)`...

    动态代理原理实例Demo

    - **Proxy.newProxyInstance()**: 这是生成动态代理对象的关键方法。它接受三个参数:`ClassLoader`,`Interface[]`和`InvocationHandler`。`ClassLoader`用于加载代理对象,`Interface[]`是代理对象需要实现的接口...

    JDK动态代理源码

    1. **Java.lang.reflect.Proxy**:这是JDK动态代理的关键类,它提供了创建动态代理对象的工厂方法`newProxyInstance()`。这个方法接收三个参数:`ClassLoader`用于加载代理类,`Interface[]`表示代理对象需要实现的...

    动态代理和静态代理demo

    `Proxy.newProxyInstance()`方法用于创建动态代理对象,传入被代理接口的类加载器、接口列表以及我们的`InvocationHandler`实例。 总结,静态代理和动态代理都是为了在不修改原始对象代码的情况下,增加额外的功能...

    动态代理的前世今生-绝对经典

    `Proxy` 类是用于创建动态代理对象的工厂,而`InvocationHandler`接口定义了代理对象调用方法时的行为。当我们创建一个代理对象时,需要提供一个实现了`InvocationHandler`的实例,并指定一组接口,代理对象将实现...

    Java中的动态代理

    3. **创建动态代理对象**:通过`Proxy.newProxyInstance()`方法创建一个实现了`HelloWorld`接口的动态代理对象。 4. **调用代理对象的方法**:最后通过调用代理对象的`sayHelloWorld()`方法,可以看到输出结果不仅...

    动态代理和cglib例子

    - 接下来,通过java.lang.reflect.Proxy类的newProxyInstance()方法,传入接口、实现类的类加载器以及自定义的InvocationHandler实现,生成动态代理对象。 - 最后,通过代理对象调用接口方法,实际上会触发...

    java动态代理源代码

    Proxy类是Java动态代理的核心,它提供了创建动态代理对象的工厂方法`newProxyInstance()`。这个方法需要三个参数:一个ClassLoader对象(用于加载生成的代理类)、一个Interface数组(代理对象需要实现的接口)和一...

    远程对象方法调用(动态代理+socket).rar

    4. **创建动态代理**:在客户端,使用`Proxy.newProxyInstance`创建一个动态代理对象,这个代理对象实现了远程接口,其内部会调用`InvocationHandler`来处理方法调用。 5. **获取远程引用**:客户端通过RMI注册表...

    Java动态代理helloworld

    1. **Proxy类**:Proxy是Java动态代理的核心类,它提供了创建动态代理对象的方法。代理对象是目标对象的代理,当调用代理对象的方法时,实际上会调用`InvocationHandler`的`invoke()`方法。 2. **InvocationHandler...

    动态代理设置监听DEMO

    在这个DEMO中,`TestProxy`可能是测试用例类,它会创建并使用动态代理对象,验证事件注入是否成功。通过这种方式,我们可以在不修改原有业务代码的基础上,灵活地添加新的功能或监控。 总结起来,Android动态代理是...

    AOP动态代理(反射机制)

    1. **Proxy类**:Proxy类的newProxyInstance()静态方法是创建动态代理对象的关键。它需要三个参数:一个ClassLoader,表示用来加载代理类的类加载器;一个Interface[],表示代理对象需要实现的接口列表;以及一个...

    JAVA实现动态代理的简单流程

    `Proxy`类提供了创建动态代理对象的方法,而`InvocationHandler`则定义了代理对象如何处理方法调用的逻辑。 #### 步骤一:定义接口与实现类 首先,我们需要定义一个接口(例如`AA`),以及该接口的一个具体实现类...

    动态代理设计模式-源码

    1. **Proxy类**:Proxy类提供了创建动态代理对象的方法——`newProxyInstance()`。这个方法需要三个参数:一个类加载器、一个接口数组以及一个InvocationHandler实例。类加载器用于加载代理对象的类,接口数组定义了...

    动态代理案列

    2. **Proxy类**:`Proxy.newProxyInstance()`是生成动态代理对象的关键方法。它接受三个参数:目标接口的类加载器、目标接口的类数组以及InvocationHandler实例。 ```java Interface interfaceImpl = (Interface) ...

    基于框架的Web开发-静态代理和动态代理原理.docx

    这样生成的动态代理对象能够透明地调用`UserDao`接口的所有方法,并在调用前后加入我们的自定义逻辑。 总结来说,Java动态代理提供了一种优雅的方式来扩展已有对象的功能,尤其在Web开发中,它简化了日志、事务管理...

Global site tag (gtag.js) - Google Analytics