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

Java 動態代理模式深度解析:從生活場景到源碼實現

     編輯:Java 綜合教學

Java 動態代理:從「鏈家找房」理解核心原理

動態代理是 Java 基礎框架(Spring AOP、RPC 框架)的基石。本文通過「鏈家中介」的生活場景,層層遞進講解 java.lang.reflect.Proxy 與 InvocationHandler 的協作機制,並給出完整可運行代碼。

核心類與接口

  • InvocationHandler:核心接口,唯一方法 invoke(Object proxy, Method method, Object[] args),所有代理方法調用均委派至此。
  • Proxy:工廠類,提供 newProxyInstance(ClassLoader, Class[] interfaces, InvocationHandler) 運行時生成代理類字節碼並實例化。

場景建模:鏈家業務擴展

  1. 接口(業務契約):LianJia 定義 sellHouse()、loan()。
  2. 被代理對象(房東):HouseMaster 實現接口,真實業務邏輯。
  3. 代理工廠(人才市場):CreatProxy 實現 InvocationHandler,持有目標對象,生成代理。
  4. 客戶端測試:通過代理調用方法,觀察攔截效果。

完整代碼實現

// 1. 業務接口
interface LianJia {
    void sellHouse();
    void loan();
}

// 2. 真實對象(房東)
class HouseMaster implements LianJia {
    public void sellHouse() { System.out.println("我有房子要賣"); }
    public void loan() { System.out.println("我要貸款做生意"); }
}

// 3. 動態代理工廠
class CreatProxy implements InvocationHandler {
    private Object target;
    public Object bind(Object target) {
        this.target = target;
        return Proxy.newProxyInstance(
            target.getClass().getClassLoader(),
            target.getClass().getInterfaces(),
            this
        );
    }
    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;
    }
}

// 4. 測試
public class Test {
    public static void main(String[] args) {
        HouseMaster hm = new HouseMaster();
        CreatProxy cp = new CreatProxy();
        LianJia proxy = (LianJia) cp.bind(hm);
        proxy.sellHouse();
        proxy.loan();
    }
}

運行輸出

【中介】準備辦理:sellHouse
我有房子要賣
【中介】辦理完成:sellHouse
【中介】準備辦理:loan
我要貸款做生意
【中介】辦理完成:loan

核心原理解析

  1. 運行時生成類:Proxy.newProxyInstance 使用 ASM 等字節碼庫動態生成實現指定接口的類,類名形如 com.sun.proxy.$Proxy0。
  2. 委派模式:生成的代理類每個方法體內均調用 handler.invoke(this, method, args),將邏輯委派給 InvocationHandler 實現。
  3. 接口限制:JDK 動態代理只能代理接口,無法代理普通類(CGLIB 通過繼承實現類代理)。
  4. 應用場景:AOP 切面(事務、日志、權限)、RPC 客戶端存根、緩存代理、延遲加載等。

靜態代理 vs 動態代理

維度靜態代理動態代理
代理類定義編寫 .java 文件,編譯期確定運行時字節碼生成
靈活性低,每個目標類需寫一個代理類高,一個 Handler 處理多接口
維護成本高低
適用範圍固定、少量場景框架級、通用攔截需求

總結

動態代理將「什麼時候做什麼事」(業務邏輯)與「如何做增強」(切面邏輯)解耦,是面向切面編程的基石。掌握其原理,有助於深入理解 Spring AOP、Dubbo、MyBatis Mapper 代理等主流框架的核心機制。

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