interface AbstractRole { void show(); }class RealRole implements AbstractRole { public void show() {...} }InvocationHandler,持有真實角色引用。public class Handler implements InvocationHandler {
private final Object realRole; // 通用持有
public Handler(Object realRole) { this.realRole = realRole; }
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("前置增強:給錢");
Object result = method.invoke(realRole, args); // 反射調用真實方法
System.out.println("後置增強:房子歸你");
return result;
}
// 工廠方法:生成代理實例
public Object createProxy() {
return Proxy.newProxyInstance(
this.getClass().getClassLoader(),
realRole.getClass().getInterfaces(), // 關鍵:代理實現所有接口
this
);
}
}
public class Test {
public static void main(String[] args) {
RealRole real = new RealRole();
Handler handler = new Handler(real); // 偽代理 (Handler)
AbstractRole proxy = (AbstractRole) handler.createProxy(); // 真代理 ($Proxy0)
proxy.show(); // 觸發 Handler.invoke()
}
}
proxy.show()
↓
$Proxy0.show() (動態生成類,實現 AbstractRole)
↓
Handler.invoke(proxy, Method(show), args[])
↓
前置增強
method.invoke(realRole, args) → RealRole.show()
後置增強
↓
return
Proxy.newProxyInstance(loader, interfaces, handler) 運行時生成一個類 $Proxy0,**實現了 interfaces 數組中的所有接口**並繼承 Proxy。因此代理實例天然是每個接口的子類型,安全向下轉型。
| 維度 | 靜態代理 | 動態代理 |
|---|---|---|
| 代理類來源 | 程序員手寫 .java | JVM 運行時字節碼生成 |
| 接口變更影響 | 需同步修改代理類 | 自動適配 (實現所有接口) |
| 適用場景 | 固定少量、需精細控制 | 通用 AOP、RPC、框架級 |
| 性能 | 直接調用 | 反射調用 (略慢,可用 MethodHandle 優化) |
MethodHandle mh = MethodHandles.lookup().unreflect(method);
mh.invokeWithArguments(realRole, args); // 比 reflect 快 10-20%
掌握 InvocationHandler + Proxy.newProxyInstance 雙核心,是理解 Spring AOP、Dubbo、MyBatis Mapper 代理等中間件原理的基石。