摘要:簡介代理模式委托模式就是使用代理對象來訪問目標對象這樣可以在目標對象執行前后來做一些邏輯處理這里使用到編程中的一個思想不要隨意去修改別人已經寫好的代碼或者方法如果需改修改可以通過代理的方式來擴展該方法代理模式通用類圖設計模式之禪文中提到為其
簡介
代理模式(委托模式)就是使用代理對象來訪問目標對象, 這樣可以在目標對象執行前后, 來做一些邏輯處理.
這里使用到編程中的一個思想:不要隨意去修改別人已經寫好的代碼或者方法,如果需改修改,可以通過代理的方式來擴展該方法.
代理模式通用類圖《設計模式之禪》文中提到: 為其它對象提供一種代理以控制對這個對象的訪問.靜態代理
靜態代理在使用時, 需要定義接口或者父類, 被代理對象與代理對象一起實現相同的接口或者是繼承相同父類.
接口: IUserDao.java
/** * 抽象主題類可以是抽象類也可以是接口, 是一個普通的業務類型定義, 無特殊要求. */ public interface IUserDao { void save(); }
目標對象: UserDao.java
/** * 抽象主題實現類 * 也叫做被委托角色 被代理角色. 是業務邏輯的具體執行者. */ public class UserDao implements IUserDao { public void save() { System.out.println("----已經保存數據!----"); } }
代理對象: UserDaoProxy.java
/** * 代理主題角色 * 也叫做委托類 代理類. 它負責對真實主題角色處理完畢前后做預處理和善后工作. */ public class UserDaoProxy implements IUserDao{ //接收保存目標對象 private IUserDao target; public UserDaoProxy(IUserDao target){ this.target=target; } public void save() { System.out.println("開始事務..."); target.save();//執行目標對象的方法 System.out.println("提交事務..."); } }
測試類: App.java
/** * 測試類 */ public class App { public static void main(String[] args) { //目標對象 UserDao target = new UserDao(); //代理對象,把目標對象傳給代理對象,建立代理關系 UserDaoProxy proxy = new UserDaoProxy(target); proxy.save();//執行的是代理的方法 } }靜態代理總結
1.可以做到在不修改目標對象的功能前提下, 對目標功能擴展.
2.缺點:
因為代理對象需要與目標對象實現一樣的接口, 所以會有很多代理類, 類太多. 同時, 一旦接口增加方法, 目標對象與代理對象都要維護.
動態代理動態代理是指在運行時動態生成代理類. 即, 代理類的字節碼將在運行時生成并載入當前代理的 ClassLoader. 現在有一個非常流行的名稱叫做面向橫切面編程, 也就是 AOP.
JDK 實現動態代理使用 GamePlayIH 來實現 InvocationHandler 接口, 作用就是產生一個對象的代理對象.
動態代理不像靜態代理那樣我們需要手動來創建一個代理對象, 而是在運行時幫我們生成一個代理對象.
InvocationHandler 是動態代理接口, 主要代理要被代理的方法. 其中 invoke 方法, 主要完成對真實方法的調用.
我們將 UserDaoProxy 類改為實現 InvocationHandler 接口.
public class UserDaoProxy implements InvocationHandler { private static String SAVE = "save"; @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (SAVE.equals(method.getName())) { System.out.println("這句代碼表示 save 方法實現類中的業務邏輯."); } return null; } }
通過 Proxy.newProxyInstance 方法來幫我們創建代理對象, 第二個參數表示代理類要實現的接口列表, 第三個參數是實現 InvocationHandler 接口的類, 就是用來處理我們接口列表中接口的所有方法的.
public class App { public static void main(String[] args) { IUserDao iUserDao = (IUserDao) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{IUserDao.class}, new UserDaoProxy()); iUserDao.save(); } }
代理對象不需要實現接口, 但是目標對象一定要實現接口, 否則不能用動態代理.
CGlib 實現動態代理上面的靜態代理和動態代理模式都是要求目標對象都要實現一個接口, 但是有時候目標對象只是一個多帶帶的對象, 并沒有實現任何的接口, 這個時候就可以使用以目標對象子類的方式來實現代理, 這種方法就叫做: Cglib代理
Cglib代理, 也叫作子類代理, 它是在內存中構建一個子類對象從而實現對目標對象功能的擴展.
JDK 的動態代理有一個限制, 就是要使用動態代理的對象必須實現一個或多個接口.
Cglib 是一個強大的高性能的代碼生成包, 它可以在運行期擴展java類與實現java接口. 它廣泛的被許多 AOP 的框架使用, 例如 Spring AOP 和 synaop , 為他們提供方法的interception(攔截).
Cglib包的底層是通過使用一個小而塊的字節碼處理框架ASM來轉換字節碼并生成新的類. 不鼓勵直接使用ASM, 因為它要求你必須對 JVM 內部結構包括 class 文件的格式和指令集都很熟悉.
使用 cglib 動態代理必須要注意, 目標對象的方法如果為 final/static, 那么就不會被攔截, 即不會執行目標對象額外的業務方法.
/** * 目標對象,沒有實現任何接口 */ public class UserDao { public void save() { System.out.println("----已經保存數據!----"); } }
/** * Cglib子類代理工廠 * 對UserDao在內存中動態構建一個子類對象 */ public class ProxyFactory implements MethodInterceptor{ //維護目標對象 private Object target; public ProxyFactory(Object target) { this.target = target; } //給目標對象創建一個代理對象 public Object getProxyInstance(){ //1.工具類 Enhancer en = new Enhancer(); //2.設置父類 en.setSuperclass(target.getClass()); //3.設置回調函數 en.setCallback(this); //4.創建子類(代理對象) return en.create(); } @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("開始事務..."); //執行目標對象的方法 Object returnValue = method.invoke(target, args); System.out.println("提交事務..."); return returnValue; } }
/** * 測試類 */ public class App { @Test public void test(){ //目標對象 UserDao target = new UserDao(); //代理對象 UserDao proxy = (UserDao)new ProxyFactory(target).getProxyInstance(); //執行代理對象的方法 proxy.save(); } }代理模式的優點
職責清晰. 真實的角色就是實現實際的業務邏輯, 不用關系其它非本職責的事務, 通過后期的代理完成一件事務, 結果就是編程簡潔清晰.
高擴展性. 實現類中的一些方法可能隨時發生變化, 只要代理類實現了接口, 不管實現類如何變化, 我們在不做任何修改的情況下就可以使用.
代理類不僅僅可以實現主題接口, 也可以實現其它接口完成不同的任務, 而代理的目的是在目標對象方法的基礎上作增強, 這種增強的本質通常就是對目標對象的方法進行攔截和過濾.鏈接
給女朋友講解什么是代理模式
代理模式(Proxy Pattern)- 最易懂的設計模式解析
代理模式原理及實例講解
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/72607.html
摘要:下面總結了它倆的異同相同點都需要實現同一個接口或者繼承同一個抽象類,并且代理角色和裝飾角色都持有被代理角色和構件角色的引用。 寫完上一篇之后有小伙伴問我有沒有寫過代理模式,想看看我的理解。原本我的設計模式系列是按照創建型-行為型-結構型的順序寫下去的,既然小伙伴誠心誠意了,我就大發慈悲的穿插一篇代理模式。開玩笑,題外話。 說起代理模式,就不由得想起經紀人,說起經紀人,就想起了...對,...
摘要:簡介代理模式和裝飾者模式是兩種常見的設計模式。這里通過構造函數的參數將被代理對象傳入到代理中,也可以通過其它方式,如提供一個方法。下面是的代碼輸出首先依然是先創建一個需要被代理的對象,然后把它傳入到的構造函數中。 簡介 代理模式和裝飾者模式是兩種常見的設計模式。代理模式是為其它對象提供一種代理以控制對這個對象的訪問。在某些情況下,一個對象不適合或者不能直接引用另一個對象,而代理對象可以...
摘要:代理設計模式代理模式為其他對象提供一種代理以控制對這個對象的訪問。代理模式是常見的設計模式之一是指不直接調用實際的對象,而是通過代理對象,來間接的調用實際的對象。對象類定義了代理對象所代表的目標對象。 代理設計模式 代理模式:為其他對象提供一種代理以控制對這個對象的訪問。代理模式是常見的設計模式之一,是指不直接調用實際的對象,而是通過代理對象,來間接的調用實際的對象。為什么要采用這種間...
閱讀 2263·2021-09-30 09:48
閱讀 3634·2021-09-24 10:27
閱讀 1791·2021-09-22 15:32
閱讀 2026·2021-08-09 13:44
閱讀 3575·2019-08-30 15:55
閱讀 1045·2019-08-29 17:12
閱讀 2000·2019-08-29 17:05
閱讀 2918·2019-08-29 13:43