写在前面:

大神和diao炸天的亲请绕道..

关于代理模式的概念这里省去,大家可以放鸟尽情搜..

关于为什么叫动态代理,个人理解是代理的类是在运行时动态生成的,大家也可以参考网上的理解..

文笔很差,所以文字较少,都在代码和注释中..

=======一点不华丽的分割线-------------------------

开门见山,lets Go..

Java中可以通过jdk提供的 Proxy.newProxyInstance静态方法来创建动态代理对象,下面先来看看这个方法的实现

[java] view plaincopy
  1. public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
  2. throws IllegalArgumentException {
  3. //InvocationHandler不能为空,因为对代理对象的所有方法调用实际上都会委托到InvocationHandler的invoke方法,
  4. //这个我们后面通过查看产生的代理类的源代码便会一目了然
  5. if (h == null) {
  6. throw new NullPointerException();
  7. }
  8. //这个是核心的地方,通过提供的ClassLoader和interface列表来产生代理类,具体的实现可以参考getProxyClass这个方法的实现,
  9. //真正的工作是由sun.misc.ProxyGenerator这个类来完成的,可以google查看具体的逻辑.在我们的程序中通过设置
  10. //System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true")可以查看产生的类文件
  11. Class cl = getProxyClass(loader, interfaces);
  12. //因为代理类继承了Proxy类.而Proxy中定义了构造函数protected Proxy(InvocationHandler h),所以可以反射得到Constructer实例
  13. //创建代理对象
  14. try {
  15. Constructor cons = cl.getConstructor(constructorParams);
  16. return (Object) cons.newInstance(new Object[] { h });
  17. } catch (NoSuchMethodException e) {
  18. throw new InternalError(e.toString());
  19. } catch (IllegalAccessException e) {
  20. throw new InternalError(e.toString());
  21. } catch (InstantiationException e) {
  22. throw new InternalError(e.toString());
  23. } catch (InvocationTargetException e) {
  24. throw new InternalError(e.toString());
  25. }
  26. }

下面通过个例子来说明下:

先来定义一个接口,jdk的动态代理基于接口来创建代理类,不能基于类的原因是java不支持多重继承,而代理类都会继承Proxy类(个人理解).

[java] view plaincopy
  1. /**
  2. * Subject
  3. *
  4. * @author Kevin Fan
  5. * @since 2013-9-13 下午2:43:33
  6. */
  7. public interface Subject {
  8. void pub(String key, String content);
  9. String sub(String key);
  10. }

再来一个具体的实现,在代理模式中可以叫它的实例可以叫target,这个是真正执行操作的对象

[java] view plaincopy
  1. /**
  2. * SimpleSubject
  3. *
  4. * @author Kevin Fan
  5. * @since 2013-9-13 下午2:45:03
  6. */
  7. public class SimpleSubject implements Subject {
  8. private Map<String, String> msg = new ConcurrentHashMap<String, String>();
  9. public void pub(String key, String content) {
  10. System.out.println("pub msg: key is " + key + ", content is " + content);
  11. msg.put(key, content);
  12. }
  13. public String sub(String key) {
  14. if (msg.containsKey(key)) {
  15. String ret = msg.get(key);
  16. System.out.println("sub msg: key is " + key + ", result is " + ret);
  17. return ret;
  18. }
  19. return null;
  20. }
  21. }

好,接下来我们来写个动态代理工厂,根据 不同的target来创建动态代理对象

[java] view plaincopy
  1. /**
  2. * SubjectProxyFactory
  3. *
  4. * @author Kevin Fan
  5. * @since 2013-9-13 下午2:47:24
  6. */
  7. public class SubjectProxyFactory {
  8. //TODO: cache
  9. public static Subject getSubject(final Subject realSubject) {
  10. return (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(), new Class[] { Subject.class },
  11. new InvocationHandler() {
  12. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  13. System.out.println("\naction before method invocation....");
  14. Object retVal = method.invoke(realSubject, args);
  15. System.out.println("action after method invocation....\n");
  16. return retVal;
  17. }
  18. });
  19. }
  20. }

可以看到这是一个简单的实现,只是在真实对象执行前后各打一句信息..

接下来用一个 main函数来把这些结合起来

[java] view plaincopy
  1. /**
  2. * Demo
  3. *
  4. * @author Kevin Fan
  5. * @since 2013-9-13 下午2:50:28
  6. */
  7. public class Demo {
  8. public static void main(String[] args) {
  9. //设置此系统属性,以查看代理类文件
  10. System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
  11. //创建真实对象
  12. Subject subj = new SimpleSubject();
  13. subj.pub("name", "kevin.fan");
  14. subj.sub("name");
  15. //创建代理对象
  16. Subject proxy = SubjectProxyFactory.getSubject(subj);
  17. proxy.pub("hobby", "r&b music");
  18. proxy.sub("name");
  19. }
  20. }

ok,小手抖一下,走你,看下执行结果

[html] view plaincopy
  1. pub msg: key is name, content is kevin.fan
  2. sub msg: key is name, result is kevin.fan
  3. action before method invocation....
  4. pub msg: key is hobby, content is r&b music
  5. action after method invocation....
  6. action before method invocation....
  7. sub msg: key is name, result is kevin.fan
  8. action after method invocation....

可以看到在调用代理对象的方法时,添加的额外动作已经生效,接下来我们看下生成的代理类的代码..

[java] view plaincopy
  1. import com.aliyun.demo.kevin.coder.lang.proxy.Subject;
  2. import java.lang.reflect.InvocationHandler;
  3. import java.lang.reflect.Method;
  4. import java.lang.reflect.Proxy;
  5. import java.lang.reflect.UndeclaredThrowableException;
  6. //这里很清楚了,代理类继承了Proxy类,并且实现了Proxy.newProxyInstance这个方法中传入的接口
  7. public final class $Proxy0 extends Proxy
  8. implements Subject
  9. {
  10. //这些方法在下面的static init block中进行初始化
  11. private static Method m4;
  12. private static Method m1;
  13. private static Method m3;
  14. private static Method m0;
  15. private static Method m2;
  16. static
  17. {
  18. try
  19. {
  20. m4 = Class.forName("com.aliyun.demo.kevin.coder.lang.proxy.Subject").getMethod("sub", new Class[] { Class.forName("java.lang.String") });
  21. m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
  22. m3 = Class.forName("com.aliyun.demo.kevin.coder.lang.proxy.Subject").getMethod("pub", new Class[] { Class.forName("java.lang.String"), Class.forName("java.lang.String") });
  23. m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
  24. m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
  25. return;
  26. }
  27. catch (NoSuchMethodException localNoSuchMethodException)
  28. {
  29. throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
  30. }
  31. catch (ClassNotFoundException localClassNotFoundException)
  32. {
  33. throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
  34. }
  35. }
  36. //构造函数,接收一个 InvocationHandler作为参数,这就是为什么Proxy.newProxyInstance方法里可以
  37. //通过InvocationHandler实例作为参数来反射获取Constructer实例
  38. public $Proxy0 paramInvocationHandler)
  39. throws
  40. {
  41. super(paramInvocationHandler);
  42. }
  43. //下面通过这个来看下代理对象中方法是怎样调用的
  44. public final String sub(String paramString)
  45. throws
  46. {
  47. try
  48. {
  49. //全部是通过调用InvocationHandler的invoke方法,传入对应的方法和参数
  50. return (String)this.h.invoke(this, m4, new Object[] { paramString });
  51. }
  52. catch (Error|RuntimeException localError)
  53. {
  54. throw localError;
  55. }
  56. catch (Throwable localThrowable)
  57. {
  58. throw new UndeclaredThrowableException(localThrowable);
  59. }
  60. }
  61. public final boolean equals(Object paramObject)
  62. throws
  63. {
  64. try
  65. {
  66. return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
  67. }
  68. catch (Error|RuntimeException localError)
  69. {
  70. throw localError;
  71. }
  72. catch (Throwable localThrowable)
  73. {
  74. throw new UndeclaredThrowableException(localThrowable);
  75. }
  76. }
  77. public final void pub(String paramString1, String paramString2)
  78. throws
  79. {
  80. try
  81. {
  82. this.h.invoke(this, m3, new Object[] { paramString1, paramString2 });
  83. return;
  84. }
  85. catch (Error|RuntimeException localError)
  86. {
  87. throw localError;
  88. }
  89. catch (Throwable localThrowable)
  90. {
  91. throw new UndeclaredThrowableException(localThrowable);
  92. }
  93. }
  94. public final int hashCode()
  95. throws
  96. {
  97. try
  98. {
  99. return ((Integer)this.h.invoke(this, m0, null)).intValue();
  100. }
  101. catch (Error|RuntimeException localError)
  102. {
  103. throw localError;
  104. }
  105. catch (Throwable localThrowable)
  106. {
  107. throw new UndeclaredThrowableException(localThrowable);
  108. }
  109. }
  110. public final String toString()
  111. throws
  112. {
  113. try
  114. {
  115. return (String)this.h.invoke(this, m2, null);
  116. }
  117. catch (Error|RuntimeException localError)
  118. {
  119. throw localError;
  120. }
  121. catch (Throwable localThrowable)
  122. {
  123. throw new UndeclaredThrowableException(localThrowable);
  124. }
  125. }
  126. }

-------------END

by Kevin Fan

from: http://blog.csdn.net/moreevan/article/details/11642445

jdk动态代理实现原理相关推荐

  1. Spring 初识Aop JDK动态代理实现 原理初显

    Spring 初识Aop JDK动态代理实现 原理初显 一.项目结构 二.具体步骤: 1.创建maven项目 创建好包结构 2.写一个TestDao接口 及实现类 3. 写一个自己的切面类 4.jav ...

  2. JDK动态代理实现原理--转载

    之前虽然会用JDK的动态代理,但是有些问题却一直没有搞明白.比如说:InvocationHandler的invoke方法是由谁来调用的,代理对象是怎么生成的,直到前几个星期才把这些问题全部搞明白了.  ...

  3. JDK动态代理实现原理详解(源码分析)

    无论是静态代理,还是Cglib动态代理,都比较容易理解,本文就通过进入源码的方式来看看JDK动态代理的实现原理进行分析 要了解动态代理的可以参考另一篇文章,有详细介绍,这里仅仅对JDK动态代理做源码分 ...

  4. 【干货】JDK动态代理的实现原理以及如何手写一个JDK动态代理

    动态代理 代理模式是设计模式中非常重要的一种类型,而设计模式又是编程中非常重要的知识点,特别是在业务系统的重构中,更是有举足轻重的地位.代理模式从类型上来说,可以分为静态代理和动态代理两种类型. 在解 ...

  5. 08.jdk动态代理原理

    课程标题<jdk动态代理底层原理分析> 课程内容: 1.什么是代理模式 2.代理模式应用场景有哪些 3.代理模式实现方式有哪些 4.静态代理与动态代理区别 5.JDK动态代理原理分析 6. ...

  6. 两万字吐血总结,代理模式及手写实现动态代理(aop原理,基于jdk动态代理)

    代理模式及手写实现动态代理 一.代理模式 1. 定义 2. 示例 (1)静态代理 (2)动态代理 3. 通用类图 4. 代理模式的优点 二.jdk动态代理实现原理 1. jdk动态代理源码分析(通过该 ...

  7. java jdk动态代理学习记录

    转载自: https://www.jianshu.com/p/3616c70cb37b JDK自带的动态代理主要是指,实现了InvocationHandler接口的类,会继承一个invoke方法,通过 ...

  8. 一文理解JDK静态代理、JDK动态代理、Cglib动态代理

    代理模式 通过代理来访问真实的对象,而不是直接去访问真正干活的对象,比如二房东租房,二房是代理者,而一房东才是真正的房东:或者说生活中的中介.Spring中的AOP就是动态代理 适用场景 需要动态修改 ...

  9. jdk动态代理proxy

    目录 jdk和cglib区别 以下案例: 定义共同行为接口 被代理类(目标类) jdk动态代理类-动态生成代理类和被代理方法的调用 解析动态生成的代理类$Proxy0.class 静态代理需要自己实现 ...

最新文章

  1. Qt + Python + OpenCV图标替换工具 之 Qt界面设计(四)
  2. 账号类型_2019年头条、百家、大鱼、企鹅四平台哪种类型的账号最受欢迎?
  3. 学会学习比学习什么更重要
  4. Linux SSHD服务安装与维护详解(一)——SSHD安装、启动与密钥认证实现
  5. git个人常用的命令
  6. 远程服务器638,638是什么意思
  7. 【前端】JS 计算贷款月付
  8. Open-DrainPush-Pull
  9. 笔记本ubuntu安装xen之殇
  10. [iOS][转]iOS 架构模式 - 简述 MVC, MVP, MVVM 和 VIPER (译)
  11. 学习笔记 c++ (简单的消息队列)
  12. 合数python_python输出100以内的质数与合数
  13. ios能玩java的模拟器_app适用于模拟器,但不适用于ios设备
  14. 特斯拉竞争对手Rivian获7亿美元融资 亚马逊领投
  15. STC单片机 VS/HX1838红外接收和发送实验
  16. CentOS如何安装向日葵并调用
  17. WIN7系统安装VisualSVN Server
  18. 让你的电脑成为移动WIFI。
  19. 软件质量保证测试——共享车位
  20. 2019年10月8日股市走势预测——02

热门文章

  1. 自动化特征工程和自动建模在风控场景的应用
  2. 信息检索与数据挖掘的常用加权技术。
  3. 开发者成功使用机器学习的十大诀窍
  4. jvm性能调优实战 -53接口超时导致的OOM
  5. 深入理解分布式技术 - Redis 分布式锁解决方案
  6. Redis进阶-Redis使用建议一二事
  7. MySQL-体系结构以及常用存储引擎MyISAM和InnoDB初探
  8. c++ 不允许使用抽象类类型的对象_Java中日期API的使用总结
  9. vue 中watch函数名_vue中避免使用函数来绑定依赖
  10. Redis对象类型与编码