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

Java 靜態代理與動態代理 (JDK Proxy) 完整實戰教學

     編輯:Java 相關知識

代理模式是 AOP 底層基石。本文對比靜態代理 (手寫代理類) 與JDK 動態代理 (運行期生成代理類),展示核心代碼與設計差異。

共用介面與實作

interface ITask { String task(String name); }
class TaskImpl implements ITask {
    public String task(String name) { System.out.println("hello " + name); return "hello " + name; }
}

一、靜態代理

class StaticProxy implements ITask {
    private ITask target;
    public StaticProxy(ITask target) { this.target = target; }
    public String task(String name) { return target.task(name); } // 轉發
}

// 使用
ITask proxy = new StaticProxy(new TaskImpl());
proxy.task("張三");

缺點:每個介面需手寫一個代理類,維護成本高。

二、JDK 動態代理 (核心: InvocationHandler + Proxy.newProxyInstance)

class DynamicProxy 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;
    }
}

// 使用
DynamicProxy dp = new DynamicProxy();
ITask task = (ITask) dp.bind(new TaskImpl());
task.task("李四");

核心差異對比

維度靜態代理JDK 動態代理
代理類數量每介面一個單一 InvocationHandler 處理所有介面
目標類要求實作介面**必須實作介面** (JDK Proxy 限制)
攔截粒度方法級 (硬編碼)方法級 (統一 invoke 邏輯)
性能直接調用反射調用 (略慢,可用 MethodHandle/ByteBuddy 優化)

CGLIB 補充

針對未實作介面的類,可用 CGLIB (繼承目標類、重寫非 final 方法) 實現動態代理,Spring AOP 預設混合使用 (介面用 JDK、類用 CGLIB)。

AOP 關聯

動態代理的 invoke 即「切面」執行點:前置通知 → 目標方法 → 後置/異常/返回通知。理解此機制,Spring @Transactional、@Async 等註解原理即豁然開朗。

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