代理模式理解
阿新 • • 發佈:2019-02-17
1./** 2. * 相親介面 3. * 4. * @author zhengt 5. * @time Jun 3, 2095 3:13:03 PM 6. */ 7.public interface XiangQinInterface { 8. /** 9. * 相親方法 10. */ 11. public void xiangQin(); 12.} 13./** 14. * 張三相親實現類 15. * 16. * @author zhengt 17. * @time Jun 3, 2095 3:14:48 PM 18. */ 19.public class ZhangSanXiangQinInterfaceImpl implements XiangQinInterface { 20. public void xiangQin() { 21. System.out.println("張三去相親,娶個漂亮老婆。"); 22. } 23.} 24.import java.lang.reflect.InvocationHandler; 25.import java.lang.reflect.Method; 26. 27./** 28. * 相親可是一輩子的大事,相親前要準備一下,打扮得帥氣些。 29. * 30. * @author zhengt 31. * @time Jun 3, 2095 3:15:48 PM 32. */ 33.public class ReadyInvocationHandler implements InvocationHandler { 34. //相親介面的實現類,也就是張三相親類 35. private Object zhangSan = null; 36. 37. public ReadyInvocationHandler(Object realSubject) { 38. this.zhangSan = realSubject; 39. } 40. 41. public Object invoke(Object proxy, Method m, Object[] args) { 42. Object result = null; 43. try { 44. /** 45. * 動態代理類$Proxy0呼叫xiangQin方法時會呼叫它自己的xiangQin方法, 46. * 而它自己的xiangQin方法裡面呼叫的是super.h.invoke(this, , ),也就是父類Proxy的h的invoke方法, 47. * 也就是ReadyInvocationHandler類的invoke方法。 48. * 所以,invoke(Object proxy, Method m, Object[] args)種的proxy實際上就是動態代理類$Proxy0, 49. * 如果你將其強轉成XiangQinInterface然後呼叫它的xiangQin方法,然後它就會呼叫super.h.invoke(this, , ),這樣就會死迴圈。 50. */ 51. /** 52. * 網上關於這裡最多問題就是Object proxy放在這裡用來做什麼呢?這個我也不知道, 53. * 不過至少我們知道它到底是個什麼東西,具體做什麼用嘛就不得而知了 54. */ 55. System.out.println(proxy.getClass().getSimpleName()); 56. System.out.println("張三相親前,代理人給他打扮了打扮。"); 57. result = m.invoke(zhangSan, args); 58. } catch (Exception ex) { 59. System.exit(1); 60. } 61. return result; 62. } 63.} 64.import java.lang.reflect.InvocationHandler; 65.import java.lang.reflect.Method; 66.import java.lang.reflect.Proxy; 67. 68./** 69. * 張三來到了婚介所(相親現場),開始相親。 70. * 71. * @author zhengt 72. * @time Jun 3, 2095 3:17:16 PM 73. */ 74.public class HunJieSuo { 75. public static void main(String args[]) { 76. //先將張三相親這個相親的實現類例項化,也就是得到XiangQinInterface介面的一個例項物件 77. XiangQinInterface zhangSan = new ZhangSanXiangQinInterfaceImpl(); 78. /** 79. * 得到ZhangSanXiangQinInterfaceImpl這個類的一個代理類,同時為代理類綁定了一個處理類ReadyInvocationHandler。 80. * 聽著很繞口,其實就是每次呼叫ZhangSanXiangQinInterfaceImpl這個子類的xiangQin方法時, 81. * 不是zhangSan這個ZhangSanXiangQinInterfaceImpl類的例項去呼叫, 82. * 而是這個ZhangSanXiangQinInterfaceImpl的代理類ReadyInvocationHandler去呼叫它自己的invoke方法, 83. * 這個invoke方法裡呢可以呼叫zhangSan這個例項的xiangQin方法 84. */ 85. /** 86. * 在java種怎樣實現動態代理呢 87. * 第一步,我們要有一個介面,還要有一個介面的實現類,而這個實現類呢就是我們要代理的物件, 88. * 所謂代理呢也就是在呼叫實現類的方法時,可以在方法執行前後做額外的工作,這個就是代理。 89. * 第二步,我們要自己寫一個在要代理類的方法執行時,能夠做額外工作的類,而這個類必須繼承InvocationHandler介面, 90. * 為什麼要繼承它呢?因為代理類的例項在呼叫實現類的方法的時候,不會調真正的實現類的這個方法, 91. * 而是轉而呼叫這個類的invoke方法(繼承時必須實現的方法),在這個方法中你可以呼叫真正的實現類的這個方法。 92. * 第三步,在要用代理類的例項去呼叫實現類的方法的時候,寫出下面兩段程式碼。 93. */ 94. XiangQinInterface proxy = (XiangQinInterface) Proxy.newProxyInstance( 95. zhangSan.getClass().getClassLoader(), 96. zhangSan.getClass().getInterfaces(), 97. new ReadyInvocationHandler(zhangSan)); 98. proxy.xiangQin(); 99. /** 100. * 這裡要解釋下中部那段長長的程式碼的意思,以及具體做了哪些工作? 101. * 第一,根據zhangSan.getClass().getClassLoader()這個要代理類的類載入器和 102. * zhangSan.getClass().getInterfaces()要代理類所實現的所有的介面 103. * 作為引數呼叫Proxy.getProxyClass(ClassLoader loader, Class<?>... interfaces) 104. * 的方法返回代理類的java.lang.Class物件,也就是得到了java動態生成的代理類$Proxy0的Class物件。 105. * 同時,java還讓這個動態生成的$Proxy0類實現了要代理類的實現的所有介面,並繼承了Proxy介面。 106. * 第二,例項化這個動態生成的$Proxy0類的一個例項,例項化代理類的建構函式為Proxy(InvocationHandler h), 107. * 也就是說要例項化這個動態生成的$Proxy0類,必須給它一個InvocationHandler引數,也就是我們自己實現的用來在代理類 108. * 方法執行前後做額外工作的類ReadyInvocationHandler。 109. * 這段程式碼Proxy.newProxyInstance(zhangSan.getClass().getClassLoader(),zhangSan.getClass().getInterfaces(),new ReadyInvocationHandler(zhangSan)) 110. * 得到的其實是一個類名叫$Proxy0 extends Proxy implements XiangQinInterface的類。 111. * 第三,將這個$Proxy0類強制轉型成XiangQinInterface型別,呼叫xiangQin方法。 112. */ 113. } 114.}