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

Java 動態代理機制深度解析:從 InvocationHandler 到 Spring AOP 核心原理

     編輯:Java 程式設計入門

動態代理兩大核心角色

角色類型核心職責
InvocationHandler介面定義代理方法攔截邏輯,唯一方法 invoke(proxy, method, args)
Proxy類別動態生成代理類別實例,靜態方法 newProxyInstance

核心 API 詳細說明

InvocationHandler.invoke 三個參數

Object invoke(Object proxy, Method method, Object[] args)
  • proxy:代理物件本身(非真實物件)
  • method:被呼叫的真實方法對應的 Method 物件
  • args:呼叫方法傳入的引數陣列

Proxy.newProxyInstance 三個參數

Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)
  • loader:載入代理類別的類別載入器
  • interfaces:代理類別實作的介面陣列(決定代理可被轉型為哪些型別)
  • h:關聯的 InvocationHandler 實例

完整實戰範例:房屋出租代理

1. 定義業務介面

public interface Subject {
    void rent();
    void hello(String str);
}

2. 真實主體實作

public class RealSubject implements Subject {
    public void rent() { System.out.println("I want to rent my house"); }
    public void hello(String str) { System.out.println("hello: " + str); }
}

3. 動態代理類別

public class DynamicProxy implements InvocationHandler {
    private Object subject;  // 真實物件

    public DynamicProxy(Object subject) { this.subject = subject; }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("before rent house");      // 前置增強
        System.out.println("Method: " + method);
        method.invoke(subject, args);                 // 委派真實物件執行
        System.out.println("after rent house");       // 後置增強
        return null;
    }
}

4. 客戶端使用

public class Client {
    public static void main(String[] args) {
        Subject realSubject = new RealSubject();
        InvocationHandler handler = new DynamicProxy(realSubject);

        Subject subject = (Subject) Proxy.newProxyInstance(
            handler.getClass().getClassLoader(),
            realSubject.getClass().getInterfaces(),
            handler
        );

        System.out.println(subject.getClass().getName()); // 輸出:$Proxy0
        subject.rent();
        subject.hello("world");
    }
}

執行結果與關鍵解析

$Proxy0
before rent house
Method: public abstract void com.xiaoluo.dynamicproxy.Subject.rent()
I want to rent my house
after rent house
before rent house
Method: public abstract void com.xiaoluo.dynamicproxy.Subject.hello(java.lang.String)
hello: world
after rent house

為什麼代理類別名稱是 $Proxy0?

JVM 運行時動態生成的類別,命名規則:$Proxy + 數字編號。它不是 InvocationHandler 也不是業務介面,但實作了指定介面,故可轉型為 Subject。

方法呼叫流程

  1. 客戶端呼叫 subject.rent()
  2. JVM 導向代理類別,轉發給關聯的 handler.invoke()
  3. invoke 中執行前置邏輯 → method.invoke(subject, args) 呼叫真實物件 → 後置邏輯

動態代理 vs 靜態代理

  • 靜態代理:編譯期確定代理類別,需為每個介面寫代理類,冗餘高
  • 動態代理:運行時生成,單一 InvocationHandler 處理多介面方法,符合開閉原則

Spring AOP 與動態代理

Spring AOP 底層正是基於 JDK 動態代理(介面代理)與 CGLIB(類別代理)實現。理解 InvocationHandler 機制,即掌握了 AOP 切面攔截、事務管理、日誌記錄等核心原理。

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