| 角色 | 類型 | 核心職責 |
|---|---|---|
| InvocationHandler | 介面 | 定義代理方法攔截邏輯,唯一方法 invoke(proxy, method, args) |
| Proxy | 類別 | 動態生成代理類別實例,靜態方法 newProxyInstance |
Object invoke(Object proxy, Method method, Object[] args)
Method 物件Object newProxyInstance(ClassLoader loader, Class>[] interfaces, InvocationHandler h)
InvocationHandler 實例public interface Subject {
void rent();
void hello(String str);
}
public class RealSubject implements Subject {
public void rent() { System.out.println("I want to rent my house"); }
public void hello(String str) { System.out.println("hello: " + str); }
}
public class DynamicProxy implements InvocationHandler {
private 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);
method.invoke(subject, args); // 委派真實物件執行
System.out.println("after rent house"); // 後置增強
return null;
}
}
public class Client {
public static void main(String[] args) {
Subject realSubject = new RealSubject();
InvocationHandler handler = new DynamicProxy(realSubject);
Subject subject = (Subject) Proxy.newProxyInstance(
handler.getClass().getClassLoader(),
realSubject.getClass().getInterfaces(),
handler
);
System.out.println(subject.getClass().getName()); // 輸出:$Proxy0
subject.rent();
subject.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 運行時動態生成的類別,命名規則:$Proxy + 數字編號。它不是 InvocationHandler 也不是業務介面,但實作了指定介面,故可轉型為 Subject。
subject.rent()handler.invoke()invoke 中執行前置邏輯 → method.invoke(subject, args) 呼叫真實物件 → 後置邏輯InvocationHandler 處理多介面方法,符合開閉原則Spring AOP 底層正是基於 JDK 動態代理(介面代理)與 CGLIB(類別代理)實現。理解 InvocationHandler 機制,即掌握了 AOP 切面攔截、事務管理、日誌記錄等核心原理。