动态代理对象

之前研究了一下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 ++;
  }

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值