Java 動態代理機制深度解析:InvocationHandler 與 Proxy 實現 AOP 核心原理
Spring AOP 的底層基石是 JDK 動態代理。本文通過接口定義、目標對象、代理類、客戶端調用的完整鏈路,圖解 InvocationHandler 與 Proxy 協作機制,助你徹底理解動態代理原理。
核心兩大組件
| 組件 | 類型 | 核心職責 |
InvocationHandler | 接口 | 定義 invoke(proxy, method, args),攔截代理方法調用,決定如何轉發/增強 |
Proxy | 類 | 提供 newProxyInstance(loader, interfaces, handler) 動態生成代理類實例 |
完整代碼演示
1. 業務接口
public interface Subject {
void rent();
void hello(String str);
}
2. 真實對象
public class RealSubject implements Subject {
@Override public void rent() { System.out.println("I want to rent my house"); }
@Override public void hello(String str) { System.out.println("hello: " + str); }
}
3. 動態代理類(實現 InvocationHandler)
public class DynamicProxy implements InvocationHandler {
private final Object subject; // 被代理目標
public DynamicProxy(Object subject) { this.subject = subject; }
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before rent house");
System.out.println("Method: " + method);
Object result = method.invoke(subject, args); // 反射調用目標方法
System.out.println("after rent house");
return result;
}
}
4. 客戶端創建代理並調用
public class Client {
public static void main(String[] args) {
Subject real = new RealSubject();
InvocationHandler handler = new DynamicProxy(real);
// 三要素:類加載器、實現接口數組、處理器
Subject proxy = (Subject) Proxy.newProxyInstance(
handler.getClass().getClassLoader(),
real.getClass().getInterfaces(),
handler
);
System.out.println(proxy.getClass().getName()); // $Proxy0
proxy.rent();
proxy.hello("world");
}
}
輸出與關鍵點解讀
$Proxy0
before rent house
Method: public abstract void com.xiaoluo.dynamicproxy.Subject.rent()
I want to rent my house
after rent house
before rent house
Method: public abstract void com.xiaoluo.dynamicproxy.Subject.hello(java.lang.String)
hello: world
after rent house
- $Proxy0:JVM 運行時動態生成的類名格式,實現了
Subject 接口,繼承 Proxy,非 DynamicProxy 類型。
- 強轉為 Subject 合法:因
newProxyInstance 第二參數傳入 real.getClass().getInterfaces(),代理類實現了這些接口,滿足多態。
- 調用流向:
proxy.rent() → 生成的代理類方法 → handler.invoke() → method.invoke(subject, args) → 真實對象。
- 增強點:
invoke 中可在目標調用前後插入邏輯(事務、日誌、權限),這正是 AOP 的本質。
JDK 動態代理 vs CGLIB