JDK动态代理与Dubbo自实现动态代理的研究

来源:互联网 发布:java自学视频百度云盘 编辑:程序博客网 时间:2024/05/17 03:37

1、何为代理?

        为了增强目标对象(委托对象)功能,在访问目标对象的路径上增加控制访问对象,该对象负责目标对象执行前后的

附加功能, 该访问控制对象即为代理对象, 这种设计模式即为代理!

      代理根据代理对象生成的时间分为 静态动态 代理, 本篇我们主要讨论动态代理。

2、主要的动态代理实现

      2.1)JDK动态代理

       JDK动态代理主要有java.lang.reflect.Proxy类实现,主要的实现的思路如下:

       a、生成以Proxy为父类,实现所有代理接口的class对象;

       b、调用上述class对象的构造器(以InvocationHandler为入参)实例化代理类;

       举个例子,辅助理解一下;

       1、定义一个代理接口, 如图

        

     2、定义一个委托类

     

   3、定义一个代理处理器

    

     我们可以根据上述的代理要求利用JDK的动态代理工具类Proxy创建代理类, 设置系统属性 sun.misc.ProxyGenerator.saveGeneratedFiles = true,

     在创建代理时, JVM会自动将生成的$Proxy*文件保存到某个默认路径下,一般是项目根路径下的com/sun/proxy 或者 sun/proxy路径下,这个可以根据

     具体的错误提示创建对应的路径, 如下是一个工具方法

     

     这里把用工具方法生成的代理类class对象反编译后的类贴出来,分析一下

package sun.proxy;import com.zhc.service.speaker.Subject;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import java.lang.reflect.UndeclaredThrowableException;public final class $Proxy0 extends Proxy  implements Subject{  private static Method m1;  private static Method m0;  private static Method m3;  private static Method m2;  public $Proxy0(InvocationHandler paramInvocationHandler)    throws   {    super(paramInvocationHandler);  }  public final boolean equals(Object paramObject)    throws   {    try    {      return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();    }    catch (RuntimeException localRuntimeException)    {      throw localRuntimeException;    }    catch (Throwable localThrowable)    {    }    throw new UndeclaredThrowableException(localThrowable);  }  public final int hashCode()    throws   {    try    {      return ((Integer)this.h.invoke(this, m0, null)).intValue();    }    catch (RuntimeException localRuntimeException)    {      throw localRuntimeException;    }    catch (Throwable localThrowable)    {    }    throw new UndeclaredThrowableException(localThrowable);  }  public final void speak()    throws   {    try    {      this.h.invoke(this, m3, null);      return;    }    catch (RuntimeException localRuntimeException)    {      throw localRuntimeException;    }    catch (Throwable localThrowable)    {    }    throw new UndeclaredThrowableException(localThrowable);  }  public final String toString()    throws   {    try    {      return (String)this.h.invoke(this, m2, null);    }    catch (RuntimeException localRuntimeException)    {      throw localRuntimeException;    }    catch (Throwable localThrowable)    {    }    throw new UndeclaredThrowableException(localThrowable);  }  static  {    try    {      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.zhc.service.speaker.Subject").getMethod("speak", new Class[0]);      m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);      return;    }    catch (NoSuchMethodException localNoSuchMethodException)    {      throw new NoSuchMethodError(localNoSuchMethodException.getMessage());    }    catch (ClassNotFoundException localClassNotFoundException)    {    }    throw new NoClassDefFoundError(localClassNotFoundException.getMessage());  }}


可以重点看一下上述类实现, 代理类实际上通过反射  m3 = Class.forName("com.zhc.service.speaker.Subject").getMethod("speak", new Class[0]); 

获取委托对象的实现方法Method对象,然后通过实现的接口方法  public final void speak()统一调用InvocationHandler的invoke方法, 那Invocationhandler

是如何传入的呢,没错就是通过代理类的带参构造器 public $Proxy0(InvocationHandler paramInvocationHandler),这里可以看一下具体的Proxy

代码实现,如图



      2.2)Dubbo的自实现的动态代理

       其实Dubbo自己实现的代理类生成机制和JDK思路是一样的,不过Dubbo没有用sun.misc.*包中的API方法,可能框架设计者不想让Dubbo太依赖

JDK的底层实现吧, 现在分析一下:

a) 通过代理接口组装代理类;

b) 构建代理类的代理;

c) 通过实例化接口,创建代理类实例;

Dubbo实现了自己的类生成器com.alibaba.dubbo.common.bytecode.ClassGenerator ,有兴趣可以分析一下,不展开了!

我直接贴代码分析吧, 这样直观一些,如图

生成代理类的class对象,如图

   构建代理类的代理实例,如图

   

  

总结一下上述创建过程, Dubbo会首先根据代理接口生成代理类的Class对象$Proxy.class,然后在创建一个Proxy的子类,该类实现了真正的创建代理类$Proxy

  的方法,然后客户通过调用该方法,返回委托对象的代理类,同时传入业务相关的InvacationHandler类型处理器。


 好了就啰嗦这么多吧。


尊重每一个坚持改变,让现状变得更好的人!!

0 0