interface Business { void doAction(); }
class BusinessImpl implements Business {
public void doAction() { System.out.println("核心業務邏輯"); }
}
class BusinessImplProxy implements Business {
private BusinessImpl target;
public void doAction() {
if (target == null) target = new BusinessImpl();
doBefore();
target.doAction();
doAfter();
}
private void doBefore() { System.out.println("前置增強:開啟事務/記錄日誌"); }
private void doAfter() { System.out.println("後置增強:提交事務/釋放資源"); }
}
// 客戶端
Business biz = new BusinessImplProxy();
biz.doAction();
痛點:每個業務接口都要手寫一個代理類,代碼膨脹、維護成本高。
核心組件:
java.lang.reflect.Proxy:代理類工廠;java.lang.reflect.InvocationHandler:統一攔截入口。interface BusinessFoo { void foo(); }
interface BusinessBar { String bar(String msg); }
class BusinessFooImpl implements BusinessFoo {
public void foo() { System.out.println("BusinessFooImpl.foo()"); }
}
class BusinessBarImpl implements BusinessBar {
public String bar(String msg) { System.out.println("BusinessBarImpl.bar()"); return msg; }
}
// 通用調用處理器
class BusinessInvocationHandler implements InvocationHandler {
private final Object target;
public BusinessInvocationHandler(Object target) { this.target = target; }
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(">>> 前置增強: " + method.getName());
Object result = method.invoke(target, args); // 反射調用真實對象
System.out.println("<<< 後置增強: " + method.getName());
return result;
}
// 工廠方法:生成代理實例
public static Object newProxy(Object target) {
Class> clazz = target.getClass();
return Proxy.newProxyInstance(
clazz.getClassLoader(),
clazz.getInterfaces(), // 僅支持接口代理
new BusinessInvocationHandler(target)
);
}
}
// 測試
public class DynamicProxyDemo {
public static void main(String[] args) {
BusinessFoo foo = (BusinessFoo) BusinessInvocationHandler.newProxy(new BusinessFooImpl());
foo.foo();
BusinessBar bar = (BusinessBar) BusinessInvocationHandler.newProxy(new BusinessBarImpl());
System.out.println(bar.bar("Hello"));
}
}
client → foo.foo()
↓
Proxy 實例 (動態生成 $Proxy0 實現 BusinessFoo)
↓
InvocationHandler.invoke(proxy, method, args)
↓
前置增強 → method.invoke(target, args) → 後置增強
↓
return result
| 維度 | 靜態代理 | JDK 動態代理 | CGLIB (繼承代理) |
|---|---|---|---|
| 代理類生成 | 編譯期手寫 | 運行時字節碼生成 | 運行時子類生成 |
| 目標要求 | 實現接口 | 必須實現接口 | 非 final 類 |
| 性能 | 直接調用最快 | 反射調用有開銷 | FastClass 索引較快 |
| 適用場景 | 固定少量接口 | 通用 AOP、接口多 | 無接口/第三方類 |
@EnableAspectJAutoProxy(proxyTargetClass=true)。理解靜態/動態代理本質,是掌握 Spring AOP、RPC 框架、中間件擴展的基石。