`

动态代理对象

    博客分类:
  • 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 ++;
  }

}

 

分享到:
评论

相关推荐

    Java反射及动态代理

    详细讲解java的reflect包的,阐述反射机制及动态代理的细节问题。其中动态代理部分内容参考网上资料。读完此文,相信会对javaf反射机制有一个完整清楚的了解。尤其应该看看其他中代码举例部分。

    java + 动态代理 + 动态代理实际应用场景

    3: 动态代理使用到基础理论:ClassLoader 加载.class字节码文件得到 , Class对象, Class对象通过 newProxyInstance 得到代理对象 4: 动态代理使用到基础理论:Class.forName("xxxx") 得到Class类 。

    MethodInterceptProxy,MethodInterceptProxy for Android。AOP、测试、数据访问框架使用它生成动态代理对象和拦截字段访问。.zip

    dexmaker的机器人。

    java 动态代理实现注解日志拦截

    java动态代理对象实现日志输出,另外再配上annotation实现注解输出。

    jdk动态代理修改返回类对象.rar

    熟悉动态代理的小伙伴都知道,java的动态代理有两个常用的方式,一个是jdk动态代理,一个是cglib,他们两个在使用上的最大区别就是前者是返回一个接口对象(其实质是Proxy类的子类),后者是返回了被代理类的类对象...

    cglib,字节码生成库是生成和转换Java字节码的高级API。它被aop、测试、数据访问框架用来生成动态代理对象和拦截字段访问。.zip

    字节码生成库是生成和转换java字节码的高级api。

    java设计模式【之】JDK动态代理【源码】【场景:帮爸爸买菜】.rar

    java设计模式【之】JDK动态代理【源码】【场景:帮爸爸买菜】.rar /** * 代理模式 * 在开发者的角度来看,创建一个代理对象,提供给用户使用,避免用户直接访问真正的对象 * 在用户角度来看,就是普通的类方法...

    Java面向对象系列[v1.0.0][使用反射生成动态代理]

    在Java的java.lang.reflect包里有个Proxy类和一个InvocationHandler接口,通过使用他们可以生成JDK动态代理类或动态代理对象 使用Proxy和InvocationHandler创建动态代理 Proxy提供了用于创建动态代理类和代理对象的...

    2020年春招最新阿里Java面试题集锦

    jdk和cglib实现的AOP实际上会在内存生成动态代理对象,还有什么其他办法实现AOP?经提示答出AspectJ以及实现原理 Spring中的对象的作用域 Singleton对象引用Prototype会发生什么 项目中怎样使用微服务? 两个服务...

    JDK动态代理(AOP)使用及原理分析视频教程课件

    动态代理是使用jdk的反射机制,创建对象的能力, 创建的是代理类的对象。 而不用你创建类文件。不用写java文件。 动态:在程序执行时,调用jdk提供的方法才能创建代理类的对象。jdk动态代理,必须有接口,目标类必须...

    Hibernate 延迟加载剖析与代理模式应用

    Hibernate 的延迟加载本质上就是代理模式的应用,当程序通过 Hibernate 装载一个实体时,默认情况下,Hibernate 并不会立即抓取它的集合属性、关联实体所以对应的记录,而是通过生成一个代理来表示这些集合属性、...

    Java 动态代理.md

    Java 动态代理 - Java 动态代理 ...如上图所示,用户不能直接使用目标对象,而是构造出一个代理对象,由代理对象作为中转,代理对象负责调用目标对象真正的行为,从而把结果返回给用户。 也就是说

    java静态代理和动态代理详解

    在代理模式中,主要有两种类型:静态代理和动态代理。 1.静态代理: 静态代理是指在编译期间就已经确定代理类和被代理类的关系,需要手动编写代理类。代理类需要实现与被代理类相同的接口,并且在代理类中持有一个被...

    cgLib与JDK动态代理的用法

    代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等...动态代理:在程序运行时,运用反射机制动态创建而成。

    基础深化和提高-java反射技术

    动态代理:通过反射可以创建动态代理对象,用于实现特定的代理逻辑。 框架和工具:在很多框架和工具中,如Spring框架、JUnit测试框架等,都广泛使用了反射技术,用于实现灵活的配置和扩展。 虽然反射技术提供了很...

    Spring框架+SpringAOP动态代理

    Spring 会使用 java.lang.reflect.Proxy 类来创建代理对象。 CGLIB 代理:用于代理没有实现接口的类或final类。CGLIB(Code Generation Library)是一个代码生成的类库,可以在运行时动态生成一个目标类的子类,并...

    Java 代理 代理模式 静态代理与动态代理 常见的动态代理实现 .md

    在故事中,小明是一个客户,它让小红帮忙购买香水,小红就成了一个代理对象,而香水提供商是一个真实的对象,可以售卖香水,小明通过代理商小红,购买到法国的香水,这就是一个代购的例子。我画了一幅图帮助理解这个...

    CGLIB动态代理+CGLIB动态代理完整代码

    我们最终是通过一个代理对象去调用方法的,那我们就要获取一个代理对象,cglib代理,是通过Enhancer这个类里面对应的一个create()方法,去生成一个代理对象的。 Enhancer创建一个被代理对象的子类并且拦截所有的方法...

    # 动态代理设计模式.md

    动态代理是一种设计模式,它允许在运行时为对象创建代理,并在代理对象上执行方法调用。代理对象可以拦截对真实对象的访问,并允许在调用前后插入附加逻辑。这种设计模式可以用于横切关注点的集中处理,如日志记录、...

    java动态代理和反射

    java动态代理 public class HireProxy implements InvocationHandler { //被代理的真实角色 private Object obj; public HireProxy(Object obj) { super(); this.obj = obj; } //第二个参数method,被...

Global site tag (gtag.js) - Google Analytics