Java設計模式學習06——靜態代理與動態代理
一、代理模式
為某個物件提供一個代理,從而控制這個代理的訪問。代理類和委託類具有共同的父類或父介面,這樣在任何使用委託類物件的地方都可以使用代理類物件替代。代理類負責請求的預處理、過濾、將請求分配給委託類處理、以及委託類處理完請求的後續處理。
二、代理模式結構
UML類圖:
由上圖代理模式的結構為:
- 抽象角色: 真實物件和代理物件的共同介面。
- 代理角色: 代理物件角色內部含有對真實物件的引用,從而可以操作真實物件,同時代理物件提供與真實物件相同的介面以便在任何時刻都能代替真實物件。同時,代理物件可以在執行真實物件操作時,附加其他的操作,相當於對真實物件進行封裝。
- 真實角色: 代理角色所代表的真實物件,是我們最終要引用的物件。
根據代理類的生成時間不同可以將代理分為靜態代理和動態代理兩種。
三、靜態代理
由程式設計師建立或工具生成代理類的原始碼,再編譯代理類。所謂靜態也就是在程式執行前就已經存在代理類的位元組碼檔案,代理類和委託類的關係在執行前就確定了。
示例程式碼:
1.抽象角色
public interface AbstractSubject {
void doSomething();
}
2.代理角色
public class ProxySubject implements AbstractSubject{
private AbstractSubject real ;
public ProxySubject(AbstractSubject real) {
this.real=real ;
}
@Override
public void doSomething() {
real.doSomething();
}
public void doOtherthing() {
}
}
3.真實角色
public class RealSubject implements AbstractSubject{
@Override
public void doSomething() {
System.out.println( "真實角色被使用" );
}
}
4.客戶端
public class Client {
public static void main(String[] args ) {
RealSubject real = new RealSubject();
ProxySubject proxy = new ProxySubject( real );
proxy.doSomething();
}
}
5.靜態代理的優缺點
優點: 業務類只需要關注業務邏輯本身,保證了業務類的重用性。這是代理的共有優點。
缺點:
- 代理物件的一個介面只服務於一種型別的物件,如果要代理的方法很多,勢必要為每一種方法都進行代理,靜態代理在程式規模稍大時就無法勝任了。
- 如果介面增加一個方法,除了所有實現類需要實現這個方法外,所有代理類也需要實現此方法。增加了程式碼維護的複雜度。
四、動態代理
動態代理類的原始碼是程式在執行期間由JVM根據反射等機制動態生成的,所以不存在代理類的位元組碼檔案。代理角色和真實角色的聯絡在程式執行時確定。
1.首先看看和動態代理相關JavaAPI
① .java.lang.reflect.Proxy
這是Java動態代理機制生成的所有代理類的父類,它提供了一組靜態的方法來為一組介面動態的生成代理類及其物件。
Proxy類的靜態方法:
//方法 1: 該方法用於獲取指定代理物件所關聯的呼叫處理器
static InvocationHandler getInvocationHandler(Object proxy )
//方法 2:該方法用於獲取關聯於指定類裝載器和一組介面的動態代理類的類物件
static Class getProxyClass(ClassLoader loader,Class[] interfaces)
//方法 3:該方法用於判斷指定類物件是否是一個動態代理類
static boolean isProxyClass(Class cl )
//方法 4:該方法用於為指定類裝載器、一組介面及呼叫處理器生成動態代理類例項
static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h )
②.java.lang.reflect.InvocationHandler
這是呼叫處理器介面,它自定義了一個 invoke 方法,用於集中處理在動態代理類物件上的方法呼叫,通常在該方法中實現對委託類的代理訪問。每次生成動態代理類物件時都要指定一個對應的呼叫處理器物件。
InvocationHandler核心方法
//該方法負責集中處理動態代理類上的所有方法呼叫。第一個引數既是代理類例項,第二個引數是被呼叫的方法物件
//第三個方法是呼叫引數。呼叫處理器根據這三個引數進行預處理或分派到委託類例項上反射執行
Object invoke(Object proxy, Method method,Object[] args )
③ .java.lang.reflect.ClassLoader
這是類裝載器類,負責將類的位元組碼裝載到 Java 虛擬機器(JVM)中併為其定義類物件,然後該類才能被使用。Proxy 靜態方法生成動態代理類同樣需要通過類裝載器來進行裝載才能使用,它與普通類的唯一區別就是其位元組碼是由 JVM 在執行時動態生成的而非預存在於任何一個 .class 檔案中。每次生成動態代理類物件時都需要指定一個類裝載器物件 。
2.動態代理實現步驟
- 實現InvocationHandler介面建立自己的呼叫處理器 。
- 給Proxy類提供ClassLoader和代理介面型別陣列建立動態代理類 。
- 執行真實角色具體任務。
示例程式碼
1.抽象角色和真實角色程式碼與上述相同 。
2. 建立自己的呼叫處理器:
public class SubjectHandler implements InvocationHandler{
AbstractSubject real;
public SubjectHandler(AbstractSubject real){
this.real=real;
}
@Override
public Object invoke(Object obj, Method method, Object[] args)throws Throwable {
System.out.println("代理類預處理任務");
//利用反射機制將請求分派給委託類處理。Method的invoke返回Object物件作為方法執行結果。
//因為示例程式沒有返回值,所以這裡忽略了返回值處理
method.invoke(real, args);
System.out.println("代理類後續處理任務");
return null;
}
}
3.客戶端 :
public class Client {
public static void main(String[] args) {
RealSubject real=new RealSubject();
SubjectHandler handler=new SubjectHandler(real);
//生成代理類物件
AbstractSubject proxy=(AbstractSubject) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{AbstractSubject.class},handler);
proxy.doSomething();
}
}
4.動態代理的優缺點
優點:
動態代理與靜態代理相比較,最大的好處是介面中宣告的所有方法都被轉移到呼叫處理器一個集中的方法中處理(InvocationHandler.invoke)。這樣,在介面方法數量比較多的時候,我們可以進行靈活處理,而不需要像靜態代理那樣每一個方法進行中轉。
不足:
誠然,Proxy 已經設計得非常優美,但是還是有一點點小小的遺憾之處,那就是它始終無法擺脫僅支援 interface 代理的桎梏,因為它的設計註定了這個遺憾。回想一下那些動態生成的代理類的繼承關係圖,它們已經註定有一個共同的父類叫 Proxy。Java 的繼承機制註定了這些動態代理類們無法實現對 class 的動態代理,原因是多繼承在 Java 中本質上就行不通。
本文動態代理部分內容大量引自:http://layznet.iteye.com/blog/1182924
相關文章
- JAVA學習篇--靜態代理VS動態代理Java
- JAVA 靜態代理 & 動態代理Java
- 代理模式詳解:靜態代理、JDK動態代理與Cglib動態代理模式JDKCGLib
- Java設計模式-之代理模式(動態代理)Java設計模式
- java靜態代理和動態代理Java
- Java靜態代理模式Java模式
- Java代理設計模式(Proxy)的四種具體實現:靜態代理和動態代理Java設計模式
- Java代理(jdk靜態代理、動態代理和cglib動態代理)JavaJDKCGLib
- 23種設計模式之代理模式(靜態代理)設計模式
- 設計模式_JAVA動態代理設計模式設計模式Java
- 輕鬆理解 Java 靜態代理/動態代理Java
- Java中的靜態代理和動態代理Java
- 靜態代理、動態代理與Mybatis的理解MyBatis
- 靜態代理和動態代理
- 設計模式總結——代理模式以及java的動態代理設計模式Java
- 設計模式:動態代理設計模式
- Java基礎系列-靜態代理和動態代理Java
- 【JAVA】代理模式之Java動態代理Java模式
- 深入理解靜態代理與JDK動態代理JDK
- Java代理之靜態代理Java
- 設計模式學習筆記(七)代理模式以及動態代理的實現設計模式筆記
- 代理模式-靜態代理解讀模式
- 【設計模式】-代理模式及動態代理詳解設計模式
- 【菜鳥學Java】12:代理模式——靜態代理怎麼玩?Java模式
- Java動態程式設計---動態代理Java程式設計
- Java靜態代理Java
- 面試常問的設計模式之代理模式的詳細解析!分析說明靜態代理模式和動態代理模式面試設計模式
- AOP之靜態代理VS動態代理
- 代理模式 - 動態代理模式
- Java動態代理與靜態代理以及它能為我們做什麼Java
- java執行原理、靜態代理和動態代理區分Java
- 3.靜態代理&動態代理&CGlibCGLib
- Java 靜態代理和動態代理的使用及原理解析Java
- Java中的靜態代理模式詳解Java模式
- android常用設計模式之代理設計模式及動態代理原理Android設計模式
- 【菜鳥學Java】13:代理模式——動態代理這樣玩!Java模式
- 23種設計模式之——動態代理模式設計模式
- 動態代理模式模式