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类型处理器。
好了就啰嗦这么多吧。
尊重每一个坚持改变,让现状变得更好的人!!
- JDK动态代理与Dubbo自实现动态代理的研究
- jdk动态代理的实现
- jdk的动态代理实现
- JDK动态代理的实现
- Java动态代理-JDK自带实现
- JDK动态动态代理和cglib动态代理的实现
- Dynamic Proxy(JDK自带的动态代理实现)
- JDK动态代理实现
- jdk动态代理实现
- 实现jdk动态代理
- jdk动态代理实现
- jdk实现动态代理
- JDK实现动态代理
- JDK动态代理实现
- jdk自带的动态代理说明
- Jdk自带的动态代理技术
- JDK 动态代理 & AOP实现动态代理
- JDK动态代理与CGLIB动态代理
- 数字精确运算BigDecimal长常用用法
- postman测接口 get/post方式
- TextView文字下划线的添加
- Spring Boot1.4版本后@ConfigurationProperties注解舍弃location参数后的解决方式
- 学习笔记-----HTML与CSS之间的关系
- JDK动态代理与Dubbo自实现动态代理的研究
- Linux学习(一)
- MVC5 + EF6 入门完整教程
- RecyclerView之使用ItemTouchHelper实现交互动画
- list对象取出重复的数据
- telerik如何在项目中被引用
- js,html 监听页面滚动高度 点击返回顶部
- 关于杀毒的解决方案
- jboss 下配置https