之前研究了一下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 ++; } }
相关推荐
3. **创建动态代理对象**:使用`Proxy.newProxyInstance`方法创建动态代理对象,传入ClassLoader、接口数组和上一步骤创建的InvocationHandler实例。 4. **调用代理对象的方法**:当调用代理对象的方法时,会自动...
2. **Proxy类**:用于创建动态代理对象,通过`newProxyInstance()`静态方法,传入类加载器、接口数组和InvocationHandler实例来生成代理对象。 3. **实现过程**:首先,你需要定义一个接口,然后创建实现该接口的...
`java.lang.reflect.Proxy` 类是用于创建动态代理对象的工厂类。我们需要使用`Proxy.newProxyInstance()`方法,传入类加载器、接口数组以及自定义的`InvocationHandler`实例,来生成代理对象。 5. **动态代理示例*...
Proxy类提供了创建动态代理对象的方法,而InvocationHandler接口定义了处理代理对象方法调用的逻辑。 1. **InvocationHandler接口**: 这个接口只有一个方法`invoke(Object proxy, Method method, Object[] args)`...
- **Proxy.newProxyInstance()**: 这是生成动态代理对象的关键方法。它接受三个参数:`ClassLoader`,`Interface[]`和`InvocationHandler`。`ClassLoader`用于加载代理对象,`Interface[]`是代理对象需要实现的接口...
1. **Java.lang.reflect.Proxy**:这是JDK动态代理的关键类,它提供了创建动态代理对象的工厂方法`newProxyInstance()`。这个方法接收三个参数:`ClassLoader`用于加载代理类,`Interface[]`表示代理对象需要实现的...
`Proxy.newProxyInstance()`方法用于创建动态代理对象,传入被代理接口的类加载器、接口列表以及我们的`InvocationHandler`实例。 总结,静态代理和动态代理都是为了在不修改原始对象代码的情况下,增加额外的功能...
`Proxy` 类是用于创建动态代理对象的工厂,而`InvocationHandler`接口定义了代理对象调用方法时的行为。当我们创建一个代理对象时,需要提供一个实现了`InvocationHandler`的实例,并指定一组接口,代理对象将实现...
3. **创建动态代理对象**:通过`Proxy.newProxyInstance()`方法创建一个实现了`HelloWorld`接口的动态代理对象。 4. **调用代理对象的方法**:最后通过调用代理对象的`sayHelloWorld()`方法,可以看到输出结果不仅...
- 接下来,通过java.lang.reflect.Proxy类的newProxyInstance()方法,传入接口、实现类的类加载器以及自定义的InvocationHandler实现,生成动态代理对象。 - 最后,通过代理对象调用接口方法,实际上会触发...
4. **创建动态代理**:在客户端,使用`Proxy.newProxyInstance`创建一个动态代理对象,这个代理对象实现了远程接口,其内部会调用`InvocationHandler`来处理方法调用。 5. **获取远程引用**:客户端通过RMI注册表...
1. **Proxy类**:Proxy是Java动态代理的核心类,它提供了创建动态代理对象的方法。代理对象是目标对象的代理,当调用代理对象的方法时,实际上会调用`InvocationHandler`的`invoke()`方法。 2. **InvocationHandler...
在这个DEMO中,`TestProxy`可能是测试用例类,它会创建并使用动态代理对象,验证事件注入是否成功。通过这种方式,我们可以在不修改原有业务代码的基础上,灵活地添加新的功能或监控。 总结起来,Android动态代理是...
1. **Proxy类**:Proxy类的newProxyInstance()静态方法是创建动态代理对象的关键。它需要三个参数:一个ClassLoader,表示用来加载代理类的类加载器;一个Interface[],表示代理对象需要实现的接口列表;以及一个...
`Proxy`类提供了创建动态代理对象的方法,而`InvocationHandler`则定义了代理对象如何处理方法调用的逻辑。 #### 步骤一:定义接口与实现类 首先,我们需要定义一个接口(例如`AA`),以及该接口的一个具体实现类...
1. **Proxy类**:Proxy类提供了创建动态代理对象的方法——`newProxyInstance()`。这个方法需要三个参数:一个类加载器、一个接口数组以及一个InvocationHandler实例。类加载器用于加载代理对象的类,接口数组定义了...
2. **Proxy类**:`Proxy.newProxyInstance()`是生成动态代理对象的关键方法。它接受三个参数:目标接口的类加载器、目标接口的类数组以及InvocationHandler实例。 ```java Interface interfaceImpl = (Interface) ...
这样生成的动态代理对象能够透明地调用`UserDao`接口的所有方法,并在调用前后加入我们的自定义逻辑。 总结来说,Java动态代理提供了一种优雅的方式来扩展已有对象的功能,尤其在Web开发中,它简化了日志、事务管理...
`Proxy.newProxyInstance()`方法用于创建动态代理对象,它需要三个参数:被代理的接口类型、一个`ClassLoader`和一个`InvocationHandler`实例。 在“动态代理模式实现界面跳转”的场景中,我们可以定义一个接口,...