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

Java 動態代理詳解:從靜態代理到 JDK 動態代理完整演進

     編輯:Java 程式設計入門

代理模式核心思想

「買肉不直接找養豬戶,找屠夫」——屠夫(代理)負責宰殺、分割、注水(增強),你(調用者)只管買肉。代理與目標實現同一接口,調用者無感知。

三階段代碼演進

階段 1:無代理(直接買)

class You { void work() { int meat = new Farmer().buyMeat(10); } }

階段 2:靜態代理(手寫屠夫類)

interface Seller { int buyMeat(int money); }

class Farmer implements Seller { public int buyMeat(int m) { return m / 2; } }

class Butcher implements Seller { // 代理類
    private Farmer farmer = new Farmer();
    public int buyMeat(int m) {
        int meat = farmer.buyMeat(m);
        return meat + 5; // 注水增強
    }
}

class You { void work() { new Butcher().buyMeat(10); } }

缺點:每個目標類都要手寫一個代理類,維護成本高。

階段 3:JDK 動態代理(運行時生成代理類)

核心兩類:

  • InvocationHandler:定義增強邏輯(注水)
  • Proxy.newProxyInstance():工廠方法生成代理對象
InvocationHandler handler = (proxy, method, args) -> {
    int meat = (int) method.invoke(new Farmer(), args); // 調用目標
    return meat + 5; // 增強
};

Seller proxy = (Seller) Proxy.newProxyInstance(
    getClass().getClassLoader(),
    new Class[]{Seller.class},
    handler
);

proxy.buyMeat(10); // 執行增強邏輯

參數詳解

參數含義本例對應
proxy生成的代理對象自身屠夫對象
method正被調用的方法對象buyMeat 方法
args調用參數數組[10] (money)

完整可運行代碼

import java.lang.reflect.*;

interface Seller { int buyMeat(int money); }
class Farmer implements Seller { public int buyMeat(int m) { return m / 2; } }

public class DynamicProxyDemo {
    public static void main(String[] args) {
        InvocationHandler h = (proxy, method, args) -> {
            int meat = (int) method.invoke(new Farmer(), args);
            return meat + 5;
        };
        Seller proxy = (Seller) Proxy.newProxyInstance(
            DynamicProxyDemo.class.getClassLoader(),
            new Class[]{Seller.class}, h);
        System.out.println("買到肉:" + proxy.buyMeat(10) + " 斤"); // 輸出 10
    }
}

動態代理 vs 靜態代理

  • 靜態:編譯期確定,代碼可見,適合固定增強
  • 動態:運行期生成,字節碼不可見,適合通用增強(事務、日志、權限)
  • 限制:JDK 動態代理**只能代理接口**,類代理需用 CGLIB/ByteBuddy

Spring AOP 底層原理

Spring 若目標實現接口 → JDK 動態代理;否則 → CGLIB 繼承代理。本質都是「生成子類/實現類,攔截方法調用,織入增強邏輯」。

總結

動態代理是框架級開發的基石,理解 InvocationHandler 三參數含義與 Proxy.newProxyInstance 三要素,即可看懂 Spring AOP、RPC 框架、中間件的核心源碼邏輯。

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