代理模式(Proxy Pattern)是Java中常用的設計模式之一,屬于結構型模式。它通過創建一個代理對象來控制對目標對象的訪問,從而在不改變目標對象的情況下,增強或修改其行為。代理模式的核心思想是為其他對象提供一個代理,并由代理對象控制對原對象的引用。
代理模式的主要應用場景包括: - 遠程代理:為遠程對象提供本地代理,隱藏網絡通信細節。 - 虛擬代理:延遲創建開銷較大的對象,直到真正需要時才創建。 - 保護代理:控制對敏感對象的訪問權限。 - 智能引用代理:在訪問對象時執行額外的操作,如記錄日志、緩存等。
代理模式的結構通常包括以下角色: - Subject(抽象主題):定義目標對象和代理對象的共同接口。 - RealSubject(真實主題):實現抽象主題接口,是代理模式中的目標對象。 - Proxy(代理):實現抽象主題接口,并持有對真實主題的引用,負責控制對真實主題的訪問。
靜態代理是最簡單的代理模式實現方式。在靜態代理中,代理類和目標類都實現相同的接口,代理類通過持有目標類的實例來調用目標類的方法,并在調用前后添加額外的邏輯。
以下是一個靜態代理的示例代碼:
// 抽象主題接口
interface Subject {
void request();
}
// 真實主題類
class RealSubject implements Subject {
@Override
public void request() {
System.out.println("RealSubject: Handling request.");
}
}
// 代理類
class Proxy implements Subject {
private RealSubject realSubject;
public Proxy(RealSubject realSubject) {
this.realSubject = realSubject;
}
@Override
public void request() {
// 前置處理
System.out.println("Proxy: Pre-processing request.");
// 調用真實主題的方法
realSubject.request();
// 后置處理
System.out.println("Proxy: Post-processing request.");
}
}
// 客戶端代碼
public class StaticProxyDemo {
public static void main(String[] args) {
RealSubject realSubject = new RealSubject();
Proxy proxy = new Proxy(realSubject);
proxy.request();
}
}
動態代理是Java中更靈活的代理模式實現方式。與靜態代理不同,動態代理在運行時動態生成代理類,無需手動編寫代理類。Java提供了兩種動態代理機制:基于接口的JDK動態代理和基于類的CGLIB動態代理。
JDK動態代理是Java標準庫提供的動態代理實現方式。它基于接口生成代理類,因此目標類必須實現至少一個接口。
以下是一個JDK動態代理的示例代碼:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
// 抽象主題接口
interface Subject {
void request();
}
// 真實主題類
class RealSubject implements Subject {
@Override
public void request() {
System.out.println("RealSubject: Handling request.");
}
}
// 動態代理處理器
class DynamicProxyHandler implements InvocationHandler {
private Object target;
public DynamicProxyHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 前置處理
System.out.println("DynamicProxy: Pre-processing request.");
// 調用目標對象的方法
Object result = method.invoke(target, args);
// 后置處理
System.out.println("DynamicProxy: Post-processing request.");
return result;
}
}
// 客戶端代碼
public class JDKDynamicProxyDemo {
public static void main(String[] args) {
RealSubject realSubject = new RealSubject();
Subject proxy = (Subject) Proxy.newProxyInstance(
realSubject.getClass().getClassLoader(),
realSubject.getClass().getInterfaces(),
new DynamicProxyHandler(realSubject)
);
proxy.request();
}
}
CGLIB(Code Generation Library)是一個強大的代碼生成庫,可以在運行時動態生成類的子類作為代理類。與JDK動態代理不同,CGLIB可以代理沒有實現接口的類。
以下是一個CGLIB動態代理的示例代碼:
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
// 真實主題類
class RealSubject {
public void request() {
System.out.println("RealSubject: Handling request.");
}
}
// 動態代理攔截器
class CglibProxyInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
// 前置處理
System.out.println("CglibProxy: Pre-processing request.");
// 調用目標對象的方法
Object result = proxy.invokeSuper(obj, args);
// 后置處理
System.out.println("CglibProxy: Post-processing request.");
return result;
}
}
// 客戶端代碼
public class CglibDynamicProxyDemo {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(RealSubject.class);
enhancer.setCallback(new CglibProxyInterceptor());
RealSubject proxy = (RealSubject) enhancer.create();
proxy.request();
}
}
代理模式在實際開發中有廣泛的應用,以下是一些常見的應用場景:
遠程代理用于隱藏網絡通信細節,客戶端通過代理對象訪問遠程服務。例如,Java RMI(遠程方法調用)就是基于遠程代理實現的。
虛擬代理用于延遲創建開銷較大的對象。例如,在加載大圖片時,可以使用虛擬代理先顯示縮略圖,等真正需要時再加載完整圖片。
保護代理用于控制對敏感對象的訪問權限。例如,在權限管理系統中,只有具有特定權限的用戶才能訪問某些資源。
智能引用代理用于在訪問對象時執行額外的操作。例如,在訪問數據庫時,可以使用代理對象記錄日志或緩存查詢結果。
代理模式是一種強大的設計模式,通過引入代理對象,可以在不修改目標對象的情況下增強或修改其行為。靜態代理實現簡單,但靈活性較差;動態代理(JDK和CGLIB)則提供了更高的靈活性,適用于復雜的應用場景。
在實際開發中,應根據具體需求選擇合適的代理模式實現方式。如果需要代理接口,可以選擇JDK動態代理;如果需要代理類,可以選擇CGLIB動態代理。通過合理使用代理模式,可以提高代碼的可維護性和擴展性。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。