动态代理技术的实现与理解
2018-03-07 11:55
369 查看
最近在看《深入理解java虚拟机 –JVM高级特性与最佳实战》这本书,看到动态代理这个部分,虽然以前学习spring的时候就学过动态代理的知识,但是这次看到,突然感受到了不一样的理解,特此分享出来,请大家多多指教。
动态代理实现小例子:
执行结果:
分析:上述代码中,唯一的“黑匣子”就是Proxy.newProxyInstance()方法,除此之外再没有任何特殊之处。这个方法返回了一个实现IHello的接口,并且代理了new Hello()实例行为的对象。跟踪这个方法的源码,可以看到其在运行时动态的生成一个描述代理类的字节码byte[] 数组,在main方法中加入下面这段代码可以在磁盘中生成该代理类的class文件:$proxy().class。
System.getProperties().put(“sun.misc.ProxyGenerator.saveGeneratedFiles”,”true”);
将该类进行反编译得到以下代码:
以上全是书中写的,以下,为我自己的理解:
代码执行关键步骤:
1、IHello hello = (IHello) new DynamicProxy().bind(new Hello());
分析:该行代码将Hello的实例传递给DynamicProxy对象,返回IHello接口类型的对象($Proxy0这个类的实例)。
2、Object obj = Proxy.newProxyInstance(originalObj.getClass().getClassLoader(), originalObj.getClass().getInterfaces(), this);
分析:该代码在程序运行时动态的生成了$Proxy0这个类的字节码,如以上代码所示,这个类实现了IHello接口的sayHello()方法。
注意:这个方法返回值是$Proxy的实例对象,所以步骤1接受的是这个。
3、hello.sayHello();
分析:通过以上分析,我们可以很明确的理解此sayHello()方法应该是$Proxy的实例中的sayHello()方法。
4、this.h.invoke(this,m3,null);
分析:this表示当前方法所属实例对象、即$Proxy的实例,this.h是父类Proxy中保存的InvocationHandler实例变量也就是DynamicProxy 这个类的实例,事实上该段代码就是调用DynamicProxy 类的invoke方法,传递的参数为sayHello()方法。
5、public Object invoke(Object proxy, Method method, Object[] args)
分析:打印“welecome”语句,然后调用Hello实例的sayHello()方法,打印“hello World” 语句!分析完毕。
动态代理实现小例子:
package ObjectCreate; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class DynamicProxyTest { interface IHello{ void sayHello(); } static class Hello implements IHello{ @Override public void sayHello() { System.out.println("hello World"); } } static class DynamicProxy implements InvocationHandler{ Object originalObj; Object bind(Object originalObj){ this.originalObj = originalObj; //通过该方法创建该对象的接口的代理对象的实例 //步骤2 Object obj = Proxy.newProxyInstance(originalObj.getClass().getClassLoader(), originalObj.getClass().getInterfaces(), this); return obj; } //步骤5 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("welecome!"); //通过反射调用实例的方法 return method.invoke(originalObj, args); } } public static void main(String[] args) { //步骤1 IHello hello = (IHello) new DynamicProxy().bind(new Hello()); //步骤3 hello.sayHello(); } }
执行结果:
分析:上述代码中,唯一的“黑匣子”就是Proxy.newProxyInstance()方法,除此之外再没有任何特殊之处。这个方法返回了一个实现IHello的接口,并且代理了new Hello()实例行为的对象。跟踪这个方法的源码,可以看到其在运行时动态的生成一个描述代理类的字节码byte[] 数组,在main方法中加入下面这段代码可以在磁盘中生成该代理类的class文件:$proxy().class。
System.getProperties().put(“sun.misc.ProxyGenerator.saveGeneratedFiles”,”true”);
将该类进行反编译得到以下代码:
package ObjectCreate; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.lang.reflect.UndeclaredThrowableException; public class $Proxy0 extends Proxy implements DynamicProxyTest.IHello{ private static Method m3; private static Method m1; private static Method m0; private static Method m2; protected $Proxy0(InvocationHandler h) { super(h); } @Override public final void sayHello(){ try{ //步骤4 this.h.invoke(this,m3,null); return; }catch(RuntimeException localRuntimeException){ throw localRuntimeException; }catch(Throwable localThrowable){ throw new UndeclaredThrowableException(localThrowable); } } //此处由于版面原因,忽略equals()、hashCode()、toString()、三个方法的代码 //这三个内容与sayHello()方法非常相似。 static { try{ m3 = Class.forName("org.fenixsoft.bytecode.DynamicProxyTest$IHello").getMethod("sayHello", new Class[0]); m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[]{Class.forName("java.lang.Object")}); m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]); m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]); }catch(NoSuchMethodException localNoSuchMethodException){ throw new NoSuchMethodError(localNoSuchMethodException.getMessage()); }catch(ClassNotFoundException localClassNotFoundException){ throw new NoClassDefFoundError(localClassNotFoundException.getMessage()); } } }
以上全是书中写的,以下,为我自己的理解:
代码执行关键步骤:
1、IHello hello = (IHello) new DynamicProxy().bind(new Hello());
分析:该行代码将Hello的实例传递给DynamicProxy对象,返回IHello接口类型的对象($Proxy0这个类的实例)。
2、Object obj = Proxy.newProxyInstance(originalObj.getClass().getClassLoader(), originalObj.getClass().getInterfaces(), this);
分析:该代码在程序运行时动态的生成了$Proxy0这个类的字节码,如以上代码所示,这个类实现了IHello接口的sayHello()方法。
注意:这个方法返回值是$Proxy的实例对象,所以步骤1接受的是这个。
3、hello.sayHello();
分析:通过以上分析,我们可以很明确的理解此sayHello()方法应该是$Proxy的实例中的sayHello()方法。
4、this.h.invoke(this,m3,null);
分析:this表示当前方法所属实例对象、即$Proxy的实例,this.h是父类Proxy中保存的InvocationHandler实例变量也就是DynamicProxy 这个类的实例,事实上该段代码就是调用DynamicProxy 类的invoke方法,传递的参数为sayHello()方法。
5、public Object invoke(Object proxy, Method method, Object[] args)
分析:打印“welecome”语句,然后调用Hello实例的sayHello()方法,打印“hello World” 语句!分析完毕。
相关文章推荐
- IOC,依赖倒置 (理解) Spring依赖注入的实现技术是:动态代理
- IOC,依赖倒置 (理解) Spring依赖注入的实现技术是:动态代理
- Spring AOP的底层实现技术---JDK动态代理
- 深入理解java动态代理的两种实现方式(JDK/Cglib)
- 深入理解Cglib动态代理及手动实现
- 使用Java的动态代理技术实现对象适配器模式
- Java基础---Java---基础加强---类加载器、委托机制、AOP、 动态代理技术、让动态生成的类成为目标类的代理、实现Spring可配置的AOP框架
- Spring AOP的底层实现技术---JDK动态代理
- Spring AOP的底层实现技术---JDK动态代理
- PHP实现依赖注入-使用反射机制和动态代理技术 - 简单思想(咋个办呢 zgbn)
- Java 动态代理的理解与Cglib动态代理实现
- Java动态代理模式理解和实现
- Spring(十)通过动态代理(JDK的Proxy)和cglib实现AOP技术
- Spring AOP的底层实现技术---JDK动态代理
- 利用JDK的中Proxy动态代理实现Spring的AOP技术
- 理解动态代理的实现过程
- Spring AOP的底层实现技术---CGLib动态代理
- 使用JDK中的Proxy技术来实现动态代理
- spring AOP的底层实现技术---JDK动态代理
- Spring AOP的底层实现技术---JDK动态代理