核心原理
- 基於 ASM 字節碼操作框架,運行時動態生成子類
- 通過繼承目標類、重寫方法實現攔截
- 無需目標類實現接口,補足 JDK 動態代理短板
- 廣泛用於 Spring AOP、Hibernate 等框架
核心 API
| 類/接口 | 作用 |
| Enhancer | 代理創建核心類,設置父類與回調 |
| MethodInterceptor | 攔截接口,intercept() 定義增強邏輯 |
| MethodProxy | 代理方法調用,invokeSuper() 調用父類方法 |
基礎示例:自定義攔截器
public class MyMethodInterceptor implements MethodInterceptor {
public String myFun(String arg) { return "hello, " + arg; }
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy)
throws Throwable {
System.out.println("[intercept] before");
String result = (String) args[0] + "...";
System.out.println("[intercept] after");
return result; // 直接返回,不調用父類方法
}
public Object createProxy() {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(MyMethodInterceptor.class);
enhancer.setCallback(this);
return enhancer.create();
}
public static void main(String[] args) {
MyMethodInterceptor target = new MyMethodInterceptor();
MyMethodInterceptor proxy = (MyMethodInterceptor) target.createProxy();
proxy.myFun("cglib test"); // 觸發攔截
}
}
通用工具類:Spring 風格封裝
public class MyCGLIBProxy implements MethodInterceptor {
private Enhancer enhancer = new Enhancer();
public Object getProxy(Class<?> clazz) {
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] args, MethodProxy proxy)
throws Throwable {
System.out.println("cglib before action");
Object result = proxy.invokeSuper(o, args); // 調用目標方法
System.out.println("cglib after action");
return result;
}
}
使用方式
MyCGLIBProxy p = new MyCGLIBProxy();
Performer proxy = (Performer) p.getProxy(TargetClass.class);
proxy.perform(); // 自動觸發 before/after
CGLIB vs JDK 動態代理
| 維度 | JDK Proxy | CGLIB |
| 前提條件 | 目標類實現接口 | 無需接口,繼承目標類 |
| 生成類型 | 實現接口的匿名類 | 目標類的子類 |
| final 方法 | 可代理 | 無法代理(無法重寫) |
| 性能(舊版) | 反射調用較慢 | FastClass 機制較快 |
| 性能(JDK 8+) | Lambda/MethodHandle 優化 | 差距縮小 |
適用場景
- 第三方庫類無接口、需增強
- Spring AOP 默認策略:有接口用 JDK,無接口用 CGLIB
- 需代理具體類而非接口的場景