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