JDK 動態代理
- 基於接口:目標類必須實現一個或多個接口。
- 生成實現該接口的匿名類 (
$Proxy0),委託 InvocationHandler.invoke。 - 無法代理未實現接口的類或 final 方法。
CGLIB
- 基於繼承:生成目標類的子類,攔截非 final 方法。
- 無需接口,但無法代理 final 類/方法、私有方法。
- 性能略優於 JDK(FastClass 機制),但生成類更大。
Spring AOP 選擇邏輯
if (targetClass.hasInterfaces()) use JdkDynamicAopProxy;
else use CglibAopProxy; // 強制 CGLIB: proxyTargetClass=true
應用場景
- 事務管理 (
@Transactional)。 - 日誌、監控、性能統計。
- 權限驗證、緩存攔截。
- 延遲加載 (Hibernate 惰性加載代理)。