最近在看 Spring AOP 部分的源码,所以对 JDK 动态代理具体是如何实现的这件事产生了很高的兴趣,而且能从源码上了解这个原理的话,也有助于对 spring-aop 模块的理解。话不多说,上代码。

    1. /**
    2. * 一般会使用实现了 InvocationHandler接口 的类作为代理对象的生产工厂,
    3. * 并且通过持有 被代理对象target,来在 invoke()方法 中对被代理对象的目标方法进行调用和增强,
    4. * 这些我们都能通过下面这段代码看懂,但代理对象是如何生成的?invoke()方法 又是如何被调用的呢?
    5. */
    6. public class ProxyFactory implements InvocationHandler {
    7. private Object target = null;
    8. public Object getInstanse(Object target){
    9. this.target = target;
    10. return Proxy.newProxyInstance(target.getClass().getClassLoader(),
    11. target.getClass().getInterfaces(), this);
    12. }
    13. @Override
    14. public Object invoke(Object proxy, Method method, Object[] args)
    15. throws Throwable {
    16. Object ret = null;
    17. System.out.println("前置增强");
    18. ret = method.invoke(target, args);
    19. System.out.println("后置增强");
    20. return ret;
    21. }
    22. }
    23. /**
    24. * 实现了 接口MyInterface 和接口的 play()方法,可以作为被代理类
    25. */
    26. public class TargetObject implements MyInterface {
    27. @Override
    28. public void play() {
    29. System.out.println("妲己,陪你玩 ~");
    30. }
    31. }
    32. /**
    33. * 测试类
    34. */
    35. public class ProxyTest {
    36. public static void main(String[] args) {
    37. TargetObject target = new TargetObject();
    38. // ProxyFactory 实现了 InvocationHandler接口,其中的 getInstanse()方法 利用 Proxy类
    39. // 生成了 target目标对象 的代理对象,并返回;且 ProxyFactory 持有对 target 的引用,可以在
    40. // invoke() 中完成对 target 相应方法的调用,以及目标方法前置后置的增强处理
    41. ProxyFactory proxyFactory = new ProxyFactory();
    42. // 这个 mi 就是 JDK 的 Proxy类 动态生成的代理类 $Proxy0 的实例,该实例中的方法都持有对
    43. // invoke()方法 的回调,所以当调用其方法时,就能够执行 invoke() 中的增强处理
    44. MyInterface mi = (MyInterface) proxyFactory.getInstanse(target);
    45. // 这样可以看到 mi 的 Class 到底是什么
    46. System.out.println(mi.getClass());
    47. // 这里实际上调用的就是 $Proxy0代理类 中对 play()方法 的实现,结合下面的代码可以看到
    48. // play()方法 通过 super.h.invoke() 完成了对 InvocationHandler对象(proxyFactory)中
    49. // invoke()方法 的回调,所以我们才能够通过 invoke()方法 实现对 target对象 方法的
    50. // 前置后置增强处理
    51. mi.play();
    52. // 总的来说,就是在 invoke()方法 中完成 target目标方法 的调用,及前置后置增强,
    53. // JDK 动态生成的代理类中对 invoke()方法 进行了回调
    54. }
    55. /**
    56. * 将 ProxyGenerator 生成的动态代理类的输出到文件中,利用反编译工具 luyten 等就可
    57. * 以看到生成的代理类的源码咯,下面给出了其反编译好的代码实现
    58. */
    59. @Test
    60. public void generatorSrc(){
    61. byte[] bytesFile = ProxyGenerator.generateProxyClass("$Proxy0", TargetObject.class.getInterfaces());
    62. FileOutputStream fos = null;
    63. try{
    64. String path = System.getProperty("user.dir") + "\\$Proxy0.class";
    65. File file = new File(path);
    66. fos = new FileOutputStream(file);
    67. fos.write(bytesFile);
    68. fos.flush();
    69. } catch (Exception e){
    70. e.printStackTrace();
    71. } finally{
    72. try {
    73. fos.close();
    74. } catch (IOException e) {
    75. // TODO Auto-generated catch block
    76. e.printStackTrace();
    77. }
    78. }
    79. }
    80. }
    81. /**
    82. * Proxy 生成的代理类,可以看到,其继承了 Proxy,并且实现了 被代理类的接口MyInterface
    83. */
    84. public final class $Proxy0 extends Proxy implements MyInterface {
    85. private static Method m1;
    86. private static Method m0;
    87. private static Method m3;
    88. private static Method m2;
    89. static {
    90. try {
    91. $Proxy0.m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
    92. $Proxy0.m0 = Class.forName("java.lang.Object").getMethod("hashCode", (Class<?>[])new Class[0]);
    93. // 实例化 MyInterface 的 play()方法
    94. $Proxy0.m3 = Class.forName("com.shuitu.test.MyInterface").getMethod("play", (Class<?>[])new Class[0]);
    95. $Proxy0.m2 = Class.forName("java.lang.Object").getMethod("toString", (Class<?>[])new Class[0]);
    96. }
    97. catch (NoSuchMethodException ex) {
    98. throw new NoSuchMethodError(ex.getMessage());
    99. }
    100. catch (ClassNotFoundException ex2) {
    101. throw new NoClassDefFoundError(ex2.getMessage());
    102. }
    103. }
    104. public $Proxy0(final InvocationHandler invocationHandler) {
    105. super(invocationHandler);
    106. }
    107. public final void play() {
    108. try {
    109. // 这个 h 其实就是我们调用 Proxy.newProxyInstance()方法 时传进去的 ProxyFactory对象(它实现了
    110. // InvocationHandler接口),该对象的 invoke()方法 中实现了对目标对象的目标方法的增强。
    111. // 看到这里,利用动态代理实现方法增强的实现原理就全部理清咯
    112. super.h.invoke(this, $Proxy0.m3, null);
    113. }
    114. catch (Error | RuntimeException error) {
    115. throw new RuntimeException();
    116. }
    117. catch (Throwable t) {
    118. throw new UndeclaredThrowableException(t);
    119. }
    120. }
    121. public final boolean equals(final Object o) {
    122. try {
    123. return (boolean)super.h.invoke(this, $Proxy0.m1, new Object[] { o });
    124. }
    125. catch (Error | RuntimeException error) {
    126. throw new RuntimeException();
    127. }
    128. catch (Throwable t) {
    129. throw new UndeclaredThrowableException(t);
    130. }
    131. }
    132. public final int hashCode() {
    133. try {
    134. return (int)super.h.invoke(this, $Proxy0.m0, null);
    135. }
    136. catch (Error | RuntimeException error) {
    137. throw new RuntimeException();
    138. }
    139. catch (Throwable t) {
    140. throw new UndeclaredThrowableException(t);
    141. }
    142. }
    143. public final String toString() {
    144. try {
    145. return (String)super.h.invoke(this, $Proxy0.m2, null);
    146. }
    147. catch (Error | RuntimeException error) {
    148. throw new RuntimeException();
    149. }
    150. catch (Throwable t) {
    151. throw new UndeclaredThrowableException(t);
    152. }
    153. }
    154. }