Java學(xué)習(xí)路線:Spring框架之動態(tài)代理,前言:動態(tài)代理是一種常用的設(shè)計模式,廣泛應(yīng)用于框架中,Spring框架的AOP特性就是應(yīng)用動態(tài)代理實現(xiàn)的,想要理解AOP的實現(xiàn)原理我們就必須先理解動態(tài)代理。 什么是代理模式 代理模式是GOF23設(shè)計模式之一,代理模式中存在代理者和被代理者,代理者和被代理者都具有相同的功能,并且代理者執(zhí)行功能時會附加一些額外的操作 如:手機工廠和代理商都具有賣東西的功能,手機代理商除了幫工廠賣手機外,還能在賣手機前打廣告推銷,賣手機后還可以進行售后服務(wù)。 代理模式的優(yōu)點: 1)符合開閉原則,不用修改被代理者任何的代碼,就能擴展新的功能 2)項目的擴展和維護比較方便 代理模式分為:靜態(tài)代理和動態(tài)代理 靜態(tài)代理 什么是靜態(tài)代理 1)代理者和被代理者都實現(xiàn)了相同的接口(或繼承相同的父類) 2)代理者包含了一個被代理者的對象 3)調(diào)用功能時,代理者會調(diào)用被代理者的功能,同時附加新的操作 1. /** 2. * 賣手機 3. */ 4. public interface SellMobilePhone { 5. 6. void sellMobilePhone(); 7. } 8. /** 9. * 小米手機工廠 10. */ 11. public class MiPhoneFactory implements SellMobilePhone{ 12. 13. public void sellMobilePhone() { 14. System.out.println("生產(chǎn)了小米9手機,賣出去!!"); 15. } 16. } 17. /** 18. * 小米代理商 19. */ 20. public class MiPhoneAgent implements SellMobilePhone { 21. 22. //被代理者,工廠對象 23. private SellMobilePhone factory; 24. 25. //通過構(gòu)造方法傳入被代理者 26. public MiPhoneAgent(SellMobilePhone factory){ 27. this.factory = factory; 28. } 29. 30. public void sellMobilePhone() { 31. System.out.println("打廣告,做活動~~~~~~~~~~~~~~~~~"); 32. //調(diào)用被代理者的方法 33. factory.sellMobilePhone(); 34. System.out.println("做售后,做推銷~~~~~~~~~~~~~~~~~"); 35. } 36. } 37. public class TestStaticProxy { 38. 39. @Test 40. public void testProxy(){ 41. //創(chuàng)建被代理者 42. SellMobilePhone factory = new MiPhoneFactory(); 43. factory.sellMobilePhone(); 44. System.out.println("---------------------------------------"); 45. //創(chuàng)建代理者 46. SellMobilePhone agent = new MiPhoneAgent(factory); 47. //調(diào)用賣手機 48. agent.sellMobilePhone(); 49. } 50. } 靜態(tài)代理的問題: 靜態(tài)代理只能適合一種業(yè)務(wù),如果有新的業(yè)務(wù),就必須創(chuàng)建新的接口和新的代理,如添加賣電腦的接口和電腦工廠,就要創(chuàng)建新的電腦代理類。 動態(tài)代理 動態(tài)代理的特點: 1) 在不修改原有類的基礎(chǔ)上,為原來類添加新的功能 2) 不需要依賴某個具體業(yè)務(wù) 動態(tài)代理分為:JDK動態(tài)代理和CGLib動態(tài)代理 區(qū)別是: JDK動態(tài)代理的被代理者必須實現(xiàn)任意接口 CGLib動態(tài)代理不用實現(xiàn)接口,是通過繼承實現(xiàn)的 JDK動態(tài)代理 實現(xiàn)步驟: 1)代理類需要實現(xiàn)InvocationHandler接口 2)實現(xiàn)invoke方法 3)通過Proxy類的newProxyInstance方法來創(chuàng)建代理對象 51. /** 52. * 動態(tài)代理 53. */ 54. public class SalesAgent implements InvocationHandler{ 55. 56. //被代理者對象 57. private Object object; 58. 59. /** 60. * 創(chuàng)建代理對象 61. * @param object 被代理者 62. * @return 代理者 63. */ 64. public Object createProxy(Object object){ 65. this.object = object; 66. //Proxy.newProxyInstance創(chuàng)建動態(tài)代理的對象,傳入被代理對象的類加載器,接口,InvocationHandler對象 67. return Proxy.newProxyInstance(object.getClass().getClassLoader(),object.getClass().getInterfaces(),this); 68. } 69. 70. /** 71. * 調(diào)用被代理者方法,同時添加新功能 72. */ 73. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 74. System.out.println("銷售之前,打廣告~~~~~~"); 75. //調(diào)用被代理者的方法 76. Object result = method.invoke(object,args); 77. System.out.println("銷售之后,做售后~~~~~~"); 78. return result; 79. } 80. } 81. public class TestInvocationHandler { 82. 83. @Test 84. public void testInvocation(){ 85. //創(chuàng)建動態(tài)代理對象 86. SalesAgent agent = new SalesAgent(); 87. //被代理對象 88. SellMobilePhone sellMobilePhone = new MiPhoneFactory(); 89. //創(chuàng)建代理對象 90. SellMobilePhone phoneProxy = (SellMobilePhone) agent.createProxy(sellMobilePhone); 91. phoneProxy.sellMobilePhone(); 92. } 93. } CGLib動態(tài)代理 特點:通過繼承實現(xiàn),被代理者必須能被繼承,通過被代理類創(chuàng)建子類,子類就是父類的代理。 94. /** 95. * CGLib動態(tài)代理 96. * 97. */ 98. public class CGLibProxy implements MethodInterceptor { 99. 100. /** 101. * 返回代理對象 102. * @param object 被代理對象 103. * @return 代理對象 104. */ 105. public Object createProxy(Object object){ 106. //創(chuàng)建加強器 107. Enhancer eh = new Enhancer(); 108. //設(shè)置被代理對象的類為父類 109. eh.setSuperclass(object.getClass()); 110. //設(shè)置代理對象的回調(diào) 111. eh.setCallback(this); 112. return eh.create(); 113. } 114. 115. public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { 116. System.out.println("售前~~~~~~CGLIB"); 117. //調(diào)用父類對象的方法 118. Object res = proxy.invokeSuper(obj, args); 119. System.out.println("售后~~~~~~CGLIB"); 120. return res; 121. } 122. } 總結(jié) 代理模式分為靜態(tài)代理和動態(tài)代理,靜態(tài)代理只能代理某一種業(yè)務(wù),動態(tài)代理可以代理各種業(yè)務(wù)而不用添加新的代理類,動態(tài)代理分為JDK動態(tài)代理和CGLib動態(tài)代理,JDK動態(tài)代理類必須實現(xiàn)某個接口,如果沒有實現(xiàn)接口則可以使用CGlib實現(xiàn)。 |
|
來自: 好程序員IT > 《Java培訓(xùn)教程》