這是我參與8月更文挑戰的第3天,活動詳情查看:8月更文挑戰java
Proxy-代理模式
代理模式
- 代理模式: Proxy Pattern. 指爲對象提供一種代理,用以控制對這個對象的訪問. 是一種結構型模式
- 代理模式包含三種角色:
- 抽象角色Subject: 聲明真實角色和代理角色共同接口方法.該類能夠是接口也能夠是抽象類
- 代理角色ProxySubject: 代理類. 代理對象內部包含對真實對象的引用,同時代理對象提供與真實對象相同的接口,能夠代替真實對象. 同時,代理對象能夠在執行真實對象操做時,附加其他的操做,至關於對真實對象進行封裝
- 真實角色RealSubject: 被代理類. 進行代理的真實對象,負責執行系統的真正的邏輯業務對象.調用真實對象方法,都要通過代理角色進行代理
- 通常代理能夠理解爲代碼加強,實際上就是在原代碼邏輯先後增長一些處理邏輯,而調用者無感知.代理模式屬於結構型模式,分爲靜態代理和動態代理
- 代理模式通用寫法
靜態代理
- 靜態代理: 須要定義接口或者父類,被代理的對象和代理對象須要實現相同的接口或者相同的父類
- 優勢:
- 能夠作到在不修改目標對象的功能前提下,對目標功能進行擴展
- 缺點:
- 由於代理對象須要與真實對象實現一樣的接口,因此會有不少代理類
- 若是接口增長方法,真實對象與代理對象都要進行維護
- 靜態代理示例
動態代理
- 動態代理特色:
- 代理對象不須要實現接口
- 動態代理是利用JDK的API, 動態地在內存中構建代理對象.須要指定建立的代理對象或者目標對象實現的接口類型
Java動態代理
- Java中JDK動態代理API所在的包 : java.lang.reflect.Proxy
- JDK實現動態代理只須要使用newProxyInstance() 方法:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h);
複製代碼
- 動態代理示例
- Java動態代理要求被代理的對象必須是一個實現了接口的對象:
- 緣由在於Java動態代理生成代理類時默認繼承的Proxy
- 根據Java的單繼承多實現的特性,只能實現對接口對象的代理
CGLIB代理
- 靜態代理模式和動態代理模式要求目標對象是一個實現了接口的對象
- 目標對象有時候只是一個單獨的對象,並無實現任何接口
- 這時候可使用目標對象子類的方式實現代理,即CGLIB代理
- CGLIB代理: 子類代理. 在內存中構建真實對象類的子類對象實現對真實對象的代理
- Java動態代理的對象必須實現一個或者多個接口.若是須要代理沒有是實現接口的類就可使用CGLIB代理
- CGLIB是一個高性能的代碼生成包,能夠在運行時期擴展java類和實現java接口,常常被應用在Spring AOP中
- CGLIB的底層是經過使用一個小而快的字節碼處理框架ASM來轉換字節碼並生成新的類.不推薦直接使用ASM框架,由於這對JVM內部結構包括class文件的格式和指令集有要求
- CGLIB代理實現:
- 須要引入cglib依賴,由於Spring中已是包含cglib功能,因此引入了spring-core依賴便可
- 引入cglib依賴後,就能夠在內存中動態構建子包
- 代理的類不能是final修飾的類,不然會報錯
- 真實對象的方法若是是final或者static, 就會被攔截,不會執行真實對象的額外業務方法
- CGLIB代理示例
代理模式和裝飾器模式區別
- UML類圖基本沒有區別,都是實現同一個接口,一個類包裝另外一個類
代理模式
- 控制訪問:
- 爲真實對象提供一種代理用於控制對這個對象的訪問
- 在不改變接口的前提下,控制對象的訪問
裝飾器模式
- 新增行爲:
- 動態的新增或者組合對象的行爲
- 在不改變接口的前提下,動態擴展對象的功能
- 裝飾器模式的核心: 動態地將屬性,功能和責任附加到對象上