Proxy动态代理的内部机制

机制分析

其实JDK的动态代理,实际上就是“反射”与“执行时动态生成字节码”二者的结合体。

$Proxy0=Proxy.newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)做了以下2件事。

  1. 根据参数 loader 和 interfaces 调用方法 Proxy 的getProxyClass(loader, interfaces)创建代理类 $Proxy0 。
    $Proxy0 类实现了interfaces的接口,并继承了Proxy类。

  2. 实例化 $Proxy0 并在构造方法中把InvocationHandler传过去,接着 $Proxy0 调用父类 Proxy 的构造器,为h赋值

// Proxy类中有一个protected构造方法,接收一个InvocationHandler

class Proxy{

    InvocationHandler h=null;

    protected Proxy(InvocationHandler h) {

     this.h = h;

    }

    ...

 }

 // $Proxy0的部分代码如下所示

 import java.lang.reflect.InvocationHandler;

 import java.lang.reflect.Method;

 import java.lang.reflect.Proxy;

 import java.lang.reflect.UndeclaredThrowableException;

 // IManager是代理实现的的接口,下面主要介绍了如何代理

 public final class $Proxy0 extends Proxy implements IManager {

 // 调用父类Proxy的构造方法传递InvocationHandler 

 public $Proxy0(InvocationHandler invocationhandler) {

    super(invocationhandler);

 }

 private static Method m1;

 private static Method m0;

 private static Method m3;

 private static Method m2;

 ....

 static {

    try {

     // 反射得到Object的方法对象(Method对象)

     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]);

     m3 = Class.forName("com.ml.test.Manager").getMethod("modify",

       new Class[0]);

     m2 = Class.forName("java.lang.Object").getMethod("toString",

       new Class[0]);

    } catch (NoSuchMethodException nosuchmethodexception) {

     throw new NoSuchMethodError(nosuchmethodexception.getMessage());

    } catch (ClassNotFoundException classnotfoundexception) {

     throw new NoClassDefFoundError(classnotfoundexception.getMessage());

    }

 }

 .......

 // 当调用代理类$proxy0的方法时,会回调$Proxy0=Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces,    //  InvocationHandler h)中定义的InvocationHandler的Invoke()方法

 //          三个参数:this---代理类本身$Proxy0

 //          m1---相对应的Method对象

 //          new Object[]{}---方法的参数,没有参数传null

 @Override

 public final boolean equals(Object obj) {

    try {

    // 这句代码回调了你写的invoke()方法

     return ((Boolean) super.h.invoke(this, m1, new Object[] { obj }))

       .booleanValue();

    } catch (Throwable throwable) {

     throw new UndeclaredThrowableException(throwable);

    }

 }


 @Override

 public final int hashCode() {

    try {

     return ((Integer) super.h.invoke(this, m0, null)).intValue();

    } catch (Throwable throwable) {

     throw new UndeclaredThrowableException(throwable);

    }

 }


 public final void modify() {

    try {

     super.h.invoke(this, m3, null);

     return;

    } catch (Error e) {

    } catch (Throwable throwable) {

     throw new UndeclaredThrowableException(throwable);

    }

 }


 @Override

 public final String toString() {

    try {

     return (String) super.h.invoke(this, m2, null);

    } catch (Throwable throwable) {

     throw new UndeclaredThrowableException(throwable);

    }

 }

 }

 // 下面演示&Proxy0的使用

 //  把得到的$Proxy0实例强制转换成IManager类型的managerProxy.

 IManager managerProxy = (Manager) Proxy.newProxyInstance(managerImpl

      .getClass().getClassLoader(), managerImpl.getClass()

      .getInterfaces(), invocationHandler);

 $Proxy0也实现了IManager接口中的所有方法,所以当调用managerProxy.modify(),就是执行下面这些代码

   try {

     super.h.invoke(this, m3, null);

     return;

    } catch (Error e) {

    } catch (Throwable throwable) {

     throw new UndeclaredThrowableException(throwable);

 }  

这样动态代理机制就实现了。

所以 JAVA 的动态代理的关键就在 Proxy.newProxyInstance(…) 方法执行时生成了 $Proxy0 的内存字节码以及 JDK 的反射机制。

上一篇:C++STL库String类实现


下一篇:C++Primer : 第十四章 :算术与关系运算符