Java 動態代理是實現 AOP(面向切面編程)、RPC 框架、聲明式事務等核心技術的基石。本文通過完整實例深度解析 java.lang.reflect.Proxy 與 InvocationHandler 的工作原理、生成的代理類結構及調用流程。
package com.fans.common.proxy;
public interface BusinessProcessor {
void processBusiness();
}
package com.fans.common.proxy;
public class BusinessProcessorImpl implements BusinessProcessor {
@Override
public void processBusiness() {
System.out.println("processing business.....");
}
}
package com.fans.common.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class BusinessProcessorHandler implements InvocationHandler {
private Object target;
public BusinessProcessorHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("You can do something here before process your business");
Object result = method.invoke(target, args); // 反射調用目標方法
System.out.println("You can do something here after process your business");
return result;
}
}
package com.fans.common.proxy;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
public class Test {
public static void main(String[] args) {
// 1. 創建目標對象
BusinessProcessorImpl bpimpl = new BusinessProcessorImpl();
// 2. 創建處理器
BusinessProcessorHandler handler = new BusinessProcessorHandler(bpimpl);
// 3. 生成代理對象
BusinessProcessor bp = (BusinessProcessor) Proxy.newProxyInstance(
bpimpl.getClass().getClassLoader(),
bpimpl.getClass().getInterfaces(),
handler
);
// 4. 調用代理方法
bp.processBusiness();
// 5. 反射檢視代理類結構
System.out.println(bp.getClass().getName());
printClassDefinition(bp.getClass());
}
// 輔助方法:打印類定義、字段、方法
public static void printClassDefinition(Class clz) { ... }
public static String getModifier(int modifier) { ... }
}
You can do something here before process your business
processing business.....
You can do something here after process your business
$Proxy0
$Proxy0 extends java.lang.reflect.Proxy implements com.fans.common.proxy.BusinessProcessor
{
java.lang.reflect.Method m1;
java.lang.reflect.Method m3;
java.lang.reflect.Method m0;
java.lang.reflect.Method m2;
boolean equals(java.lang.Object);
java.lang.String toString();
int hashCode();
void processBusiness();
}
java.lang.reflect.ProxynewProxyInstance 第二參數指定的所有接口equals、toString、hashCode 委託給 InvocationHandlerMethod 字段(如 m0-m3),初始化時通過反射獲取$Proxy0(InvocationHandler h),調用 super(h) 存入父類 Proxy.hProxyGenerator.generateProxyClass)Proxy(InvocationHandler) 創建實例,並初始化 Method 字段
// 客戶端代碼
bp.processBusiness();
// 實際執行流程
1. bp 引用指向 $Proxy0 實例
2. 調用 $Proxy0.processBusiness()
3. $Proxy0.processBusiness() 內部實現:
return h.invoke(this, m3, null); // m3 對應 processBusiness
4. 進入 BusinessProcessorHandler.invoke()
5. 執行前置邏輯 → method.invoke(target, args) → 執行後置邏輯
| 要點 | 說明 |
|---|---|
| 接口驅動 | 只能代理接口,不能代理類(CGLIB 可代理類) |
| InvocationHandler 核心 | 所有方法調用統一委派給 invoke(),實現橫切關注點分離 |
| Method 字段緩存 | 代理類初始化時通過反射獲取並緩存 Method 對象,避免重複查找 |
| Object 方法處理 | equals/hashCode/toString 也走 invoke,需在 handler 中區分處理 |
| 序列化支持 | 代理類實現 Serializable 需所有接口可序列化,且 handler 可序列化 |
invoke 中區分業務方法與 Object 方法,避免誤觸發切面邏輯method.invoke,性能敏感場景可考慮 MethodHandle 或字節碼生成庫Proxy.getProxyClass 與 newProxyInstance 的區別:前者僅獲取 Class,後者直接實例化動態代理通過「接口 + 反射 + 動態字節碼生成」實現了無侵入的方法攔截。理解其生成的代理類結構、Method 緩存機制、InvocationHandler 委派模型,是掌握 Spring AOP、RPC 框架、中間件開發的關鍵基石。建議結合 ProxyGenerator 生成的源碼深入研讀,體會「為接口編程」的設計哲學。