之前研究了一下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的reflect包的,阐述反射机制及动态代理的细节问题。其中动态代理部分内容参考网上资料。读完此文,相信会对javaf反射机制有一个完整清楚的了解。尤其应该看看其他中代码举例部分。
3: 动态代理使用到基础理论:ClassLoader 加载.class字节码文件得到 , Class对象, Class对象通过 newProxyInstance 得到代理对象 4: 动态代理使用到基础理论:Class.forName("xxxx") 得到Class类 。
dexmaker的机器人。
java动态代理对象实现日志输出,另外再配上annotation实现注解输出。
熟悉动态代理的小伙伴都知道,java的动态代理有两个常用的方式,一个是jdk动态代理,一个是cglib,他们两个在使用上的最大区别就是前者是返回一个接口对象(其实质是Proxy类的子类),后者是返回了被代理类的类对象...
字节码生成库是生成和转换java字节码的高级api。
java设计模式【之】JDK动态代理【源码】【场景:帮爸爸买菜】.rar /** * 代理模式 * 在开发者的角度来看,创建一个代理对象,提供给用户使用,避免用户直接访问真正的对象 * 在用户角度来看,就是普通的类方法...
在Java的java.lang.reflect包里有个Proxy类和一个InvocationHandler接口,通过使用他们可以生成JDK动态代理类或动态代理对象 使用Proxy和InvocationHandler创建动态代理 Proxy提供了用于创建动态代理类和代理对象的...
jdk和cglib实现的AOP实际上会在内存生成动态代理对象,还有什么其他办法实现AOP?经提示答出AspectJ以及实现原理 Spring中的对象的作用域 Singleton对象引用Prototype会发生什么 项目中怎样使用微服务? 两个服务...
动态代理是使用jdk的反射机制,创建对象的能力, 创建的是代理类的对象。 而不用你创建类文件。不用写java文件。 动态:在程序执行时,调用jdk提供的方法才能创建代理类的对象。jdk动态代理,必须有接口,目标类必须...
Hibernate 的延迟加载本质上就是代理模式的应用,当程序通过 Hibernate 装载一个实体时,默认情况下,Hibernate 并不会立即抓取它的集合属性、关联实体所以对应的记录,而是通过生成一个代理来表示这些集合属性、...
Java 动态代理 - Java 动态代理 ...如上图所示,用户不能直接使用目标对象,而是构造出一个代理对象,由代理对象作为中转,代理对象负责调用目标对象真正的行为,从而把结果返回给用户。 也就是说
在代理模式中,主要有两种类型:静态代理和动态代理。 1.静态代理: 静态代理是指在编译期间就已经确定代理类和被代理类的关系,需要手动编写代理类。代理类需要实现与被代理类相同的接口,并且在代理类中持有一个被...
代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等...动态代理:在程序运行时,运用反射机制动态创建而成。
动态代理:通过反射可以创建动态代理对象,用于实现特定的代理逻辑。 框架和工具:在很多框架和工具中,如Spring框架、JUnit测试框架等,都广泛使用了反射技术,用于实现灵活的配置和扩展。 虽然反射技术提供了很...
Spring 会使用 java.lang.reflect.Proxy 类来创建代理对象。 CGLIB 代理:用于代理没有实现接口的类或final类。CGLIB(Code Generation Library)是一个代码生成的类库,可以在运行时动态生成一个目标类的子类,并...
在故事中,小明是一个客户,它让小红帮忙购买香水,小红就成了一个代理对象,而香水提供商是一个真实的对象,可以售卖香水,小明通过代理商小红,购买到法国的香水,这就是一个代购的例子。我画了一幅图帮助理解这个...
我们最终是通过一个代理对象去调用方法的,那我们就要获取一个代理对象,cglib代理,是通过Enhancer这个类里面对应的一个create()方法,去生成一个代理对象的。 Enhancer创建一个被代理对象的子类并且拦截所有的方法...
动态代理是一种设计模式,它允许在运行时为对象创建代理,并在代理对象上执行方法调用。代理对象可以拦截对真实对象的访问,并允许在调用前后插入附加逻辑。这种设计模式可以用于横切关注点的集中处理,如日志记录、...
java动态代理 public class HireProxy implements InvocationHandler { //被代理的真实角色 private Object obj; public HireProxy(Object obj) { super(); this.obj = obj; } //第二个参数method,被...