代理模式:為其他對象提供一個代理,以控制對該對象的訪問。核心三角色:
public interface Subject { void doSomething(); }
public class RealSubject implements Subject {
public void doSomething() { System.out.println("業務邏輯..."); }
}
public class Proxy implements Subject {
private Subject real;
public Proxy(Subject real) { this.real = real; }
public void doSomething() {
// 前置增強
real.doSomething();
// 後置增強
}
}
客戶端只知代理,不知真實主題。代理構造器中創建真實主題:
public class Proxy implements Subject {
private RealSubject real = new RealSubject(); // 內部創建
public void doSomething() { real.doSomething(); }
}
必須通過真實主題獲取代理,真實主題不直接對外暴露:
public class RealSubject implements Subject {
public Subject getProxy() { return new Proxy(this); } // 只能通過此法獲取代理
public void doSomething() {
if (proxy != null) System.out.println("被代理執行...");
else System.out.println("請先訪問代理...");
}
}
| 類型 | 核心作用 | 典型例子 |
|---|---|---|
| 遠程代理 | 隱藏網絡通訊細節 | RPC、RMI、Dubbo |
| 虛擬代理 | 延遲創建開銷大對象 | 圖片懒加載、大文件預覽 |
| 複製代理 | 寫時復制,延遲克隆 | CopyOnWriteArrayList |
| 保護代理 | 權限控制,不同角色不同權限 | Spring Security、數據庫視圖 |
| 緩存代理 | 緩存計算結果,共享複用 | Hibernate 二級緩存、Guava Cache |
| 防火牆代理 | 過濾惡意請求 | API 閘關、WAF |
| 同步代理 | 多線程安全訪問 | Collections.synchronizedList |
| 智能引用代理 | 引用計數、訪問日誌 | 引用計數 GC、訪問統計 |
| 複雜隱藏代理 | 隱藏系統複雜度,統一入口 | 外觀模式變體、微服務網關 |
InvocationHandler 攔截代理模式是控制訪問、增強功能、解耦關注點的利器。靜態代理代碼固定,動態代理(JDK/CGLIB/ByteBuddy)運行時生成字節碼更靈活。實戰中優先使用成熟框架(Spring AOP),手寫代理僅用於學習或極簡場景。理解九大場景有助於識別何時引入代理。