首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 動態代理 核心機制深度解析:InvocationHandler + Proxy.newProxyInstance

     編輯:Java 相關知識

三大角色回顧

  • 抽象角色:interface AbstractRole { void show(); }
  • 真實角色:class RealRole implements AbstractRole { public void show() {...} }
  • 代理角色:不直接實現接口,而是實現 InvocationHandler,持有真實角色引用。

InvocationHandler 實現

public class Handler implements InvocationHandler {
    private final Object realRole; // 通用持有
    public Handler(Object realRole) { this.realRole = realRole; }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("前置增強:給錢");
        Object result = method.invoke(realRole, args); // 反射調用真實方法
        System.out.println("後置增強:房子歸你");
        return result;
    }

    // 工廠方法:生成代理實例
    public Object createProxy() {
        return Proxy.newProxyInstance(
            this.getClass().getClassLoader(),
            realRole.getClass().getInterfaces(), // 關鍵:代理實現所有接口
            this
        );
    }
}

客戶端調用

public class Test {
    public static void main(String[] args) {
        RealRole real = new RealRole();
        Handler handler = new Handler(real);          // 偽代理 (Handler)
        AbstractRole proxy = (AbstractRole) handler.createProxy(); // 真代理 ($Proxy0)
        proxy.show(); // 觸發 Handler.invoke()
    }
}

關鍵流程圖解

proxy.show()
    ↓
$Proxy0.show() (動態生成類,實現 AbstractRole)
    ↓
Handler.invoke(proxy, Method(show), args[])
    ↓
前置增強
method.invoke(realRole, args) → RealRole.show()
後置增強
    ↓
return

為什麼能強轉為 AbstractRole?

Proxy.newProxyInstance(loader, interfaces, handler) 運行時生成一個類 $Proxy0,**實現了 interfaces 數組中的所有接口**並繼承 Proxy。因此代理實例天然是每個接口的子類型,安全向下轉型。

動態代理 vs 靜態代理 對比

維度靜態代理動態代理
代理類來源程序員手寫 .javaJVM 運行時字節碼生成
接口變更影響需同步修改代理類自動適配 (實現所有接口)
適用場景固定少量、需精細控制通用 AOP、RPC、框架級
性能直接調用反射調用 (略慢,可用 MethodHandle 優化)

進階:MethodHandle 替代反射 (Java 7+)

MethodHandle mh = MethodHandles.lookup().unreflect(method);
mh.invokeWithArguments(realRole, args); // 比 reflect 快 10-20%

掌握 InvocationHandler + Proxy.newProxyInstance 雙核心,是理解 Spring AOP、Dubbo、MyBatis Mapper 代理等中間件原理的基石。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved