靜態代理:代理類在編譯期確定,.class 文件已存在。
動態代理:代理類在運行時通過反射動態生成字節碼,無需預先定義代理類文件。JDK 動態代理基於接口,核心類為 java.lang.reflect.Proxy 和 InvocationHandler。
// 1. 業務接口
public interface Service {
void add();
void update();
}
// 2. 目標實現
public class AService implements Service {
public void add() { System.out.println("AService add"); }
public void update() { System.out.println("AService update"); }
}
// 3. 調用處理器(核心邏輯)
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("before-----------------------------"); // 前置增強
Object result = method.invoke(target, args); // 調用目標方法
System.out.println("after------------------------------"); // 後置增強
return result;
}
}
// 4. 客戶端使用
public class Client {
public static void main(String[] args) {
Service target = new AService();
MyInvocationHandler handler = new MyInvocationHandler(target);
// 動態生成代理實例
Service proxy = (Service) Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
handler
);
proxy.add(); // 輸出: before -> AService add -> after
proxy.update(); // 輸出: before -> AService update -> after
}
}
Class 對象byte[]InvocationHandlerpublic final class $Proxy0 extends Proxy implements Service {
protected $Proxy0(InvocationHandler h) { super(h); }
public final void add() {
try {
super.h.invoke(this, m3, null); // m3 為 add 方法的 Method 對象
} catch (Error | RuntimeException e) { throw e; }
catch (Throwable t) { throw new UndeclaredThrowableException(t); }
}
public final void update() { /* 類似結構 */ }
// equals、hashCode、toString 也被重寫委託給 handler
}
關鍵點:代理類繼承 Proxy、實現目標接口、構造器接收 InvocationHandler、所有接口方法重寫為調用 handler.invoke()。
Object 的 final 方法(如 getClass)不會進入 invokeSerializable 需 handler 也可序列化