「買肉不直接找養豬戶,找屠夫」——屠夫(代理)負責宰殺、分割、注水(增強),你(調用者)只管買肉。代理與目標實現同一接口,調用者無感知。
class You { void work() { int meat = new Farmer().buyMeat(10); } }
interface Seller { int buyMeat(int money); }
class Farmer implements Seller { public int buyMeat(int m) { return m / 2; } }
class Butcher implements Seller { // 代理類
private Farmer farmer = new Farmer();
public int buyMeat(int m) {
int meat = farmer.buyMeat(m);
return meat + 5; // 注水增強
}
}
class You { void work() { new Butcher().buyMeat(10); } }
缺點:每個目標類都要手寫一個代理類,維護成本高。
核心兩類:
InvocationHandler:定義增強邏輯(注水)Proxy.newProxyInstance():工廠方法生成代理對象InvocationHandler handler = (proxy, method, args) -> {
int meat = (int) method.invoke(new Farmer(), args); // 調用目標
return meat + 5; // 增強
};
Seller proxy = (Seller) Proxy.newProxyInstance(
getClass().getClassLoader(),
new Class[]{Seller.class},
handler
);
proxy.buyMeat(10); // 執行增強邏輯
| 參數 | 含義 | 本例對應 |
|---|---|---|
| proxy | 生成的代理對象自身 | 屠夫對象 |
| method | 正被調用的方法對象 | buyMeat 方法 |
| args | 調用參數數組 | [10] (money) |
import java.lang.reflect.*;
interface Seller { int buyMeat(int money); }
class Farmer implements Seller { public int buyMeat(int m) { return m / 2; } }
public class DynamicProxyDemo {
public static void main(String[] args) {
InvocationHandler h = (proxy, method, args) -> {
int meat = (int) method.invoke(new Farmer(), args);
return meat + 5;
};
Seller proxy = (Seller) Proxy.newProxyInstance(
DynamicProxyDemo.class.getClassLoader(),
new Class[]{Seller.class}, h);
System.out.println("買到肉:" + proxy.buyMeat(10) + " 斤"); // 輸出 10
}
}
Spring 若目標實現接口 → JDK 動態代理;否則 → CGLIB 繼承代理。本質都是「生成子類/實現類,攔截方法調用,織入增強邏輯」。
動態代理是框架級開發的基石,理解 InvocationHandler 三參數含義與 Proxy.newProxyInstance 三要素,即可看懂 Spring AOP、RPC 框架、中間件的核心源碼邏輯。