java.lang.reflect.Proxy + InvocationHandlerInvocationHandler.invoke。// 介面
public interface Calculator { int add(int a, int b); int sub(int a, int b); }
// 實作
public class CalculatorImpl implements Calculator { ... }
// 代理處理器
public class MyInvocationHandler implements InvocationHandler {
private Object target;
public MyInvocationHandler(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;
}
}
// 使用
Calculator target = new CalculatorImpl();
Calculator proxy = (Calculator) Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new MyInvocationHandler(target)
);
proxy.add(1, 2); // 輸出前置/後置並返回 3
net.sf.cglib),Spring 內建。final 類、final 方法、private 方法。public class CglibProxy implements MethodInterceptor {
private Object target;
public Object getInstance(Object target) {
this.target = target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("CGLIB 前置");
Object result = proxy.invokeSuper(obj, args); // 呼叫父類方法
System.out.println("CGLIB 後置");
return result;
}
}
// 使用
CalculatorImpl target = new CalculatorImpl();
CalculatorImpl proxy = (CalculatorImpl) new CglibProxy().getInstance(target);
proxy.add(10, 20);
| 維度 | JDK Proxy | CGLIB |
|---|---|---|
| 代理類型 | 介面代理 | 類繼承代理 |
| 生成代理速度 | 快 | 慢 (需字節碼操作) |
| 代理方法調用速度 | 較慢 (反射調用) | 快 (FastClass 機制索引調用) |
| 適用場景 | 單例、長生命週期物件 (一次生成多次調用) | 頻繁創建代理、目標無介面 |
Spring 預決策:目標有介面用 JDK,無介面用 CGLIB (可強制 proxy-target-class=true)。