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

Java 靜態代理與動態代理(JDK 與 CGLIB)深度解析

     編輯:Java 相關知識

代理模式是常見的設計模式,代理類與委託類實現相同介面,代理類負責預處理、過濾、轉發請求及後續處理。依建立時機分為靜態代理與動態代理。

靜態代理

由程式設計師建立或工具生成代碼,編譯期即存在 .class 檔案。缺點:一個代理類只能服務一個介面,易產生大量重複代碼。

範例結構

  • Count 介面:定義 queryCount()、updateCount()
  • CountImpl:委託類,實作業務邏輯
  • CountProxy:代理類,實作 Count,持有 CountImpl 參考,方法中添加事務處理邏輯
  • TestCount:測試類,建立代理並呼叫方法

JDK 動態代理

運行時透過反射機制動態生成代理類,核心為 java.lang.reflect.Proxy 與 InvocationHandler 介面。

關鍵組件

  • InvocationHandler:invoke(Object proxy, Method method, Object[] args) 定義代理邏輯
  • Proxy.newProxyInstance():(ClassLoader loader, Class[] interfaces, InvocationHandler h) 動態生成代理物件

範例實作

public class BookFacadeProxy implements InvocationHandler {
    private Object target;
    
    public Object bind(Object target) {
        this.target = target;
        return Proxy.newProxyInstance(
            target.getClass().getClassLoader(),
            target.getClass().getInterfaces(),
            this
        );
    }
    
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("事務開始");
        Object result = method.invoke(target, args);
        System.out.println("事務結束");
        return result;
    }
}

限制:目標類必須實作介面,無法代理未實作介面的類。

CGLIB 動態代理

針對類而非介面,原理是生成目標類的子類並覆寫方法實現增強。無法代理 final 修飾的類與方法。

核心類

  • Enhancer:CGLIB 的字節碼增強器
  • MethodInterceptor:攔截器介面,intercept(Object obj, Method method, Object[] args, MethodProxy proxy)

範例實作

public class BookFacadeCglib implements MethodInterceptor {
    private Object target;
    
    public Object getInstance(Object target) {
        this.target = target;
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(this.target.getClass());
        enhancer.setCallback(this);
        return enhancer.create();
    }
    
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("事務開始");
        proxy.invokeSuper(obj, args); // 呼叫父類方法
        System.out.println("事務結束");
        return null;
    }
}

兩者對比總結

特性JDK 動態代理CGLIB 動態代理
代理目標介面類(生成子類)
核心機制反射 + Proxy字節碼處理 + 繼承
final 限制無無法代理 final 類/方法
效能生成快、調用稍慢生成慢、調用快
適用場景目標實作介面目標未實作介面、需高效能調用

Spring AOP 預設:介面用 JDK,類用 CGLIB(可透過 proxy-target-class="true" 強制 CGLIB)。

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