前言
代理模式最典型的應用就是AOP,本文結合主要講解了代理模式的幾種實現方式:靜態(tài)代理和動態(tài)代理,這里動態(tài)代理又可以分為jdk代理和Cglib代理。
代理,顧名思義,即代替被請求者來處理相關事務。代理對象一般會全權代理被請求者的全部只能,客戶訪問代理對象就像在訪問被請求者一樣,雖然代理對象最終還是可能會訪問被請求者,但是其可以在請求之前或者請求之后進行一些額外的工作,或者說客戶的請求不合法,直接拒絕客戶的請求。如下圖所示為代理模式的一份簡圖:

代理模式的角色:
- ISubject:代理者與被代理者共同實現的接口,可以理解為需要代理的行為;
- SubjectImpl:被代理者,其為具有某種特定行為的實現者;
- SubjectProxy:代理者,其會全權代理SubjectImpl所具有的功能,在實現其功能的基礎上做一些額外的工作;
- Client:客戶端,客戶端訪問代理者與訪問被代理者具有類似的效果,其無法區(qū)分訪問的是代理者還是被代理者。
1. 靜態(tài)代理
靜態(tài)代理模式也即上圖中描述的這種模式,從圖中可以看出,SubjectProxy保存一個ISubject實例,當客戶端調用SubjectProxy的request()方法時,其除了做額外的工作之外,還會調用ISubject實例的request()方法。如下是這三個類的一個簡單實現:
public interface ISubject {
void request();
}
public class SubjectImpl implements ISubject {
@Override
public void request() {
System.out.println("request SubjectImpl.");
}
}
public class SubjectProxy implements ISubject {
private ISubject target;
public SubjectProxy(ISubject target) {
this.target = target;
}
@Override
public void request() {
System.out.println("before safety check.");
target.request();
System.out.println("after safety check.");
}
}
可以看到,代理對象在調用被代理對象的方法之前和之后都打印了相關的語句。如下是客戶端請求示例:
public class Client {
@Test
public void testStaticProxy() {
ISubject subject = new SubjectImpl();
ISubject proxy = new SubjectProxy(subject);
proxy.request();
}
}
運行上述用例,可得到如下結果:
before safety check.
request SubjectImpl.
after safety check.
優(yōu)點:
從客戶端訪問方式可以看出,客戶端獲取的是一個實現ISubject接口的實例,其在調用的request()方法實際上是代理對象的request()方法。這種代理方式稱為靜態(tài)代理,并且這種代理方式也是效率最高的一種方式,因為所有的類都是已經編寫完成的,客戶端只需要取得代理對象并且執(zhí)行即可。
缺點:
靜態(tài)代理雖然效率較高,但其也有不可避免的缺陷。可以看到,客戶端在調用代理對象時,使用的是代理對象和被代理對象都實現的一個接口,我們可以將該接口理解為定義了某一種業(yè)務需求的實現規(guī)范。如果有另外一份業(yè)務需求(如進行數據修改),其與當前需求并行的,沒有交集的,但是其在進行正常業(yè)務之外所做的安全驗證工作與當前需求是一致的。那我們要實現相同的對象代理功能(安全驗證),靜態(tài)代理方式需要為每個接口實現一個代理類,而這些代理類中的代碼幾乎是一致的。這在大型系統(tǒng)中將會產生很大的維護問題。
2. 動態(tài)代理
可以查看我的另一篇文章:
JDK動態(tài)代理和CGLIB動態(tài)代理:http://www.itdecent.cn/p/085170b0228f