動態代理為 Facade、Bridge、Interceptor、Decorator、Proxy (遠程/虛擬)、Adapter 等模式提供了運行時生成代理類的替代方案。雖然傳統靜態類也能實現,但動態代理更簡潔、彈性,能消除大量手寫或代碼生成的 Stub 類。
核心思想:建立「存根」或「替身」物件,接收請求並轉發給真實執行工作的物件。
呼叫端持有介面引用,無法區分是代理還是真實物件。代理負責:查找真實物件、參數編碼/解碼 (Marshalling/Unmarshalling)、網路傳輸、異常轉換。
rmic 編譯期生成 _Stub / _Skel 類。rmic,開發體驗大幅提升。核心介面:java.lang.reflect.InvocationHandler
public interface InvocationHandler {
Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}
InvocationHandler。invoke(),參數包含:代理物件本身、被調用 Method 物件、實際參數陣列。return method.invoke(target, args); (委派給目標物件)。Proxy.newProxyInstance() 工廠方法建立。invoke() 中開啟/提交事務、檢查權限。public class LoggingHandler implements InvocationHandler {
private final Object target;
public LoggingHandler(Object target) { this.target = target; }
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
long start = System.nanoTime();
try {
return method.invoke(target, args);
} finally {
System.out.printf("[%s] %s 執行耗時: %d ms%n",
new Date(), method.getName(), (System.nanoTime() - start) / 1_000_000);
}
}
}
// 使用方式
MyInterface target = new MyImpl();
MyInterface proxy = (MyInterface) Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new LoggingHandler(target));
proxy.doSomething(); // 自動記錄日誌
動態代理是 Java 反射機制的皇冠上的明珠,將「橫切關注點」與「業務邏輯」乾淨分離,是 AOP (面向切面編程) 的基石。Spring AOP、Hibernate Lazy Loading、RMI 等核心框架均大量依賴它。