好程式設計師Java學習路線之Spring框架之動態代理
好程式設計師 Java 學習路線之 Spring 框架之動態代理, 前言: 動態代理是一種常用的設計模式,廣泛應用於框架中, Spring 框架的 AOP 特性就是應用動態代理實現的,想要理解 AOP 的實現原理我們就必須先理解動態代理。
什麼是代理模式
代理模式 是 GOF23 設計模式之一, 代理模式中存在代理者和被代理者,代理者和被代理者都具有相同的功能,並且代理者執行功能時會附加一些額外的操作
如:手機工廠和代理商都具有賣東西的功能,手機代理商除了幫工廠賣手機外,還能在賣手機前打廣告推銷,賣手機後還可以進行售後服務。
代理模式的 優點 :
1 )符合開閉原則,不用修改被代理者任何的程式碼,就能擴充套件新的功能
2 )專案的擴充套件和維護比較方便
代理模式分為:靜態代理和動態代理
靜態代理
什麼是靜態代理
1 )代理者和被代理者都實現了相同的介面(或繼承相同的父類)
2 )代理者包含了一個被代理者的物件
3 )呼叫功能時,代理者會呼叫被代理者的功能,同時附加新的操作
- /**
- * 賣手機
- */
- public interface SellMobilePhone {
- void sellMobilePhone();
- }
- /**
- * 小米手機工廠
- */
- public class MiPhoneFactory implements SellMobilePhone{
- public void sellMobilePhone() {
- System.out.println(" 生產了小米 9 手機,賣出去!! ");
- }
- }
- /**
- * 小米代理商
- */
- public class MiPhoneAgent implements SellMobilePhone {
- // 被代理者,工廠物件
- private SellMobilePhone factory;
- // 透過構造方法傳入被代理者
- public MiPhoneAgent(SellMobilePhone factory){
- this.factory = factory;
- }
- public void sellMobilePhone() {
- System.out.println(" 打廣告,做活動 ~~~~~~~~~~~~~~~~~");
- // 呼叫被代理者的方法
- factory.sellMobilePhone();
- System.out.println(" 做售後,做推銷 ~~~~~~~~~~~~~~~~~");
- }
- }
- public class TestStaticProxy {
- @Test
- public void testProxy(){
- // 建立被代理者
- SellMobilePhone factory = new MiPhoneFactory();
- factory.sellMobilePhone();
- System.out.println("---------------------------------------");
- // 建立代理者
- SellMobilePhone agent = new MiPhoneAgent(factory);
- // 呼叫賣手機
- agent.sellMobilePhone();
- }
- }
靜態代理的問題:
靜態代理只能適合一種業務,如果有新的業務,就必須建立新的介面和新的代理,如新增賣電腦的介面和電腦工廠,就要建立新的電腦代理類。
動態代理
動態代理的特點:
1) 在不修改原有類的基礎上,為原來類新增新的功能
2) 不需要依賴某個具體業務
動態代理分為:JDK 動態代理 和 CGLib 動態代理
區別是:
JDK 動態代理的 被代理者必須實現任意介面
CGLib 動態代理不用實現介面,是透過繼承實現的
JDK 動態代理
實現步驟:
1 )代理類需要實現 InvocationHandler 介面
2 )實現 invoke 方法
3 )透過 Proxy 類的 newProxyInstance 方法來建立代理物件
- /**
- * 動態代理
- */
- public class SalesAgent implements InvocationHandler{
- // 被代理者物件
- private Object object;
- /**
- * 建立代理物件
- * @param object 被代理者
- * @return 代理者
- */
- public Object createProxy(Object object){
- this.object = object;
- //Proxy.newProxyInstance 建立動態代理的物件,傳入被代理物件的類載入器,介面, InvocationHandler 物件
- return Proxy.newProxyInstance(object.getClass().getClassLoader(),object.getClass().getInterfaces(),this);
- }
- /**
- * 呼叫被代理者方法,同時新增新功能
- */
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- System.out.println(" 銷售之前,打廣告 ~~~~~~");
- // 呼叫被代理者的方法
- Object result = method.invoke(object,args);
- System.out.println(" 銷售之後,做售後 ~~~~~~");
- return result;
- }
- }
- public class TestInvocationHandler {
- @Test
- public void testInvocation(){
- // 建立動態代理物件
- SalesAgent agent = new SalesAgent();
- // 被代理物件
- SellMobilePhone sellMobilePhone = new MiPhoneFactory();
- // 建立代理物件
- SellMobilePhone phoneProxy = (SellMobilePhone) agent.createProxy(sellMobilePhone);
- phoneProxy.sellMobilePhone();
- }
- }
CGLib 動態代理
特點:透過繼承實現,被代理者必須能被繼承,透過被代理類建立子類,子類就是父類的代理。
- /**
- * CGLib 動態代理
- *
- */
- public class CGLibProxy implements MethodInterceptor {
- /**
- * 返回代理物件
- * @param object 被代理物件
- * @return 代理物件
- */
- public Object createProxy(Object object){
- // 建立加強器
- Enhancer eh = new Enhancer();
- // 設定被代理物件的類為父類
- eh.setSuperclass(object.getClass());
- // 設定代理物件的回撥
- eh.setCallback(this);
- return eh.create();
- }
- public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
- System.out.println(" 售前 ~~~~~~CGLIB");
- // 呼叫父類物件的方法
- Object res = proxy.invokeSuper(obj, args);
- System.out.println(" 售後 ~~~~~~CGLIB");
- return res;
- }
- }
總結
代理模式分為靜態代理和動態代理,靜態代理只能代理某一種業務,動態代理可以代理各種業務而不用新增新的代理類,動態代理分為 JDK 動態代理和 CGLib 動態代理, JDK 動態代理類必須實現某個介面,如果沒有實現介面則可以使用 CGlib 實現。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69913892/viewspace-2651031/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 好程式設計師Java學習路線分享MyBatis之Spring整合程式設計師JavaMyBatisSpring
- 好程式設計師Java學習路線之集程式設計師Java
- 好程式設計師Java學習路線之SpringMVC之基本配置程式設計師JavaSpringMVC
- 好程式設計師Java學習路線分享MyBatis之基本使用程式設計師JavaMyBatis
- 好程式設計師Java學習路線分享SpringMVC之MVC概述程式設計師JavaSpringMVC
- 好程式設計師Java學習路線之MySQL的執行計劃程式設計師JavaMySql
- 好程式設計師Java學習路線分享Java框架怎麼搭建程式設計師Java框架
- 好程式設計師Java學習路線分享SpringMVC之請求和響應程式設計師JavaSpringMVC
- 好程式設計師Java學習路線分享MyBatis之關聯查詢程式設計師JavaMyBatis
- 好程式設計師Java分享Spring框架之AOP的基本配置程式設計師JavaSpring框架
- 好程式設計師Java乾貨分享Spring框架之IOC原理程式設計師JavaSpring框架
- 好程式設計師Java學習路線JSP物件程式設計師JavaJS物件
- 好程式設計師Java學習路線分享SpringCloud程式設計師JavaSpringGCCloud
- 好程式設計師大資料學習路線之mapreduce概述程式設計師大資料
- 好程式設計師Java學習路線分享Java面試題之載入機制程式設計師Java面試題
- 好程式設計師Java學習路線之Java中的物件流和序列化程式設計師Java物件
- 好程式設計師Java學習路線之springboot和ssm開發的區別程式設計師JavaSpring BootSSM
- 好程式設計師Java學習路線分享MyBatis之執行緒最佳化程式設計師JavaMyBatis執行緒
- 好程式設計師Java學習路線分享Spring常見面試題程式設計師JavaSpring面試題
- 好程式設計師大資料學習路線之zookeeper乾貨程式設計師大資料
- 好程式設計師大資料學習路線分享spark之Scala程式設計師大資料Spark
- 好程式設計師Python學習路線之python爬蟲入門程式設計師Python爬蟲
- 好程式設計師web前端學習路線之Javascript物件導向程式設計師Web前端JavaScript物件
- 好程式設計師Java學習路線分享Spring建立Bean的3種方式程式設計師JavaSpringBean
- 好程式設計師大資料學習路線分享Scala系列之物件程式設計師大資料物件
- 好程式設計師大資料學習路線之hive儲存格式程式設計師大資料Hive
- 好程式設計師web學習路線初步認知react框架程式設計師WebReact框架
- 好程式設計師Java學習路線分享mybatis對映程式設計師JavaMyBatis
- 好程式設計師告訴你Java架構師學習路線程式設計師Java架構
- 好程式設計師Java教程Java動態代理機制詳解程式設計師Java
- 好程式設計師Java學習路線分享Java-String常用方法程式設計師Java
- 好程式設計師大資料學習路線之hive表的查詢程式設計師大資料Hive
- 好程式設計師大資料學習路線之Logstach與flume對比程式設計師大資料
- 好程式設計師大資料學習路線分享Scala系列之抽象類程式設計師大資料抽象
- 好程式設計師大資料學習路線分享大資料之字串程式設計師大資料字串
- 好程式設計師大資料學習路線分享Scala系列之陣列程式設計師大資料陣列
- 好程式設計師大資料學習路線分享Scala系列之泛型程式設計師大資料泛型
- 好程式設計師Java學習路線分享原生Ajax的使用程式設計師Java