Java——深入解析 CGlib 與 JDK 動態代理:原理、區別與實踐

在這里插入圖片描述

在 Java 開發中,動態代理是實現 AOP(面向切面編程)的核心技術,廣泛應用于日志記錄、事務管理、權限控制等場景。其中,JDK 動態代理和 CGlib 是兩種最常用的動態代理實現方式。本文將從原理、區別、使用場景等方面深入解析這兩種技術,幫助開發者更好地理解和選擇。

一、動態代理的基本概念

動態代理是一種在運行時動態生成代理類的技術,無需手動編寫代理類代碼。其核心作用是:在不修改目標對象代碼的前提下,對目標對象的方法進行增強(如在方法執行前后添加日志、性能監控等邏輯)。

簡單來說,動態代理就像給目標對象 “套了一層殼”,所有對目標對象的調用都會先經過這層殼,從而實現增強邏輯的統一管理。

二、JDK 動態代理

1. 原理

JDK 動態代理是 Java 官方提供的代理技術,基于接口和反射機制實現:

  • 要求目標類必須實現一個或多個接口
  • 運行時,JDK 會動態生成一個實現了目標類所有接口的代理類($ProxyXXX)。
  • 代理類通過調用InvocationHandler接口的invoke方法,將增強邏輯與目標方法的執行結合起來。

2. 核心接口:InvocationHandler

public interface InvocationHandler {// proxy:代理對象本身// method:目標方法// args:目標方法的參數Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}

代理類的所有方法調用都會被轉發到invoke方法,開發者需在該方法中實現增強邏輯。

3. 實現示例

步驟 1:定義目標接口和實現類
// 目標接口
public interface UserDao {void add();
}// 目標類(實現接口)
public class UserDaoImpl implements UserDao {@Overridepublic void add() {System.out.println("執行UserDao的add方法");}
}
步驟 2:實現 InvocationHandler
public class JdkProxyHandler implements InvocationHandler {// 目標對象(被代理的原始對象)private Object target;public JdkProxyHandler(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 增強邏輯:方法執行前System.out.println("JDK代理:方法執行前(日志記錄)");// 執行目標方法Object result = method.invoke(target, args);// 增強邏輯:方法執行后System.out.println("JDK代理:方法執行后(日志記錄)");return result;}
}
步驟 3:生成代理對象并使用
public class JdkProxyDemo {public static void main(String[] args) {// 目標對象UserDao target = new UserDaoImpl();// 生成代理對象(通過Proxy類的newProxyInstance方法)UserDao proxy = (UserDao) Proxy.newProxyInstance(target.getClass().getClassLoader(), // 類加載器target.getClass().getInterfaces(),  // 目標類實現的接口new JdkProxyHandler(target)         // 增強邏輯處理器);// 調用代理對象的方法(實際會執行增強邏輯+目標方法)proxy.add();}
}
輸出結果
JDK代理:方法執行前(日志記錄)
執行UserDao的add方法
JDK代理:方法執行后(日志記錄)

三、CGlib 動態代理

1. 原理

CGlib(Code Generation Library)是一個第三方字節碼生成庫,基于繼承實現動態代理:

  • 不要求目標類實現接口,通過生成目標類的子類作為代理類。
  • 運行時,CGlib 會動態生成目標類的子類,并重寫目標類的非 final 方法。
  • 代理邏輯通過MethodInterceptor接口的intercept方法實現。

2. 核心接口:MethodInterceptor

public interface MethodInterceptor {// obj:代理對象(目標類的子類)// method:目標方法// args:目標方法的參數// proxy:方法代理對象(用于調用目標方法)Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable;
}

3. 實現示例

步驟 1:添加 CGlib 依賴(Maven)
<dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.3.0</version>
</dependency>
步驟 2:定義目標類(無需實現接口)
public class UserService {public void update() {System.out.println("執行UserService的update方法");}
}
步驟 3:實現 MethodInterceptor
public class CglibInterceptor implements MethodInterceptor {// 目標對象private Object target;public CglibInterceptor(Object target) {this.target = target;}@Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {// 增強邏輯:方法執行前System.out.println("CGlib代理:方法執行前(性能監控)");// 執行目標方法(通過代理對象調用父類方法)Object result = proxy.invokeSuper(obj, args);// 增強邏輯:方法執行后System.out.println("CGlib代理:方法執行后(性能監控結束)");return result;}
}
步驟 4:生成代理對象并使用
public class CglibDemo {public static void main(String[] args) {// 目標對象UserService target = new UserService();// CGlib增強器(用于生成代理類)Enhancer enhancer = new Enhancer();// 設置父類(目標類)enhancer.setSuperclass(UserService.class);// 設置回調(增強邏輯)enhancer.setCallback(new CglibInterceptor(target));// 生成代理對象(目標類的子類)UserService proxy = (UserService) enhancer.create();// 調用代理對象的方法proxy.update();}
}
輸出結果
CGlib代理:方法執行前(性能監控)
執行UserService的update方法
CGlib代理:方法執行后(性能監控結束)

四、JDK 動態代理 vs CGlib 動態代理

對比維度JDK 動態代理CGlib 動態代理
底層技術基于接口 + 反射基于繼承 + 字節碼生成(ASM 庫)
目標類要求必須實現接口可無接口(但不能是 final 類 / 方法)
代理類生成實現目標接口的代理類繼承目標類的子類
效率反射調用,效率較低(JDK 8+后優化明顯)直接調用子類方法,效率較高
靈活性僅能代理接口方法可代理類中所有非 final 方法
依賴JDK 內置,無需額外依賴需要引入 CGlib 庫

關鍵區別總結:

  1. 接口依賴:JDK 動態代理強制要求目標類實現接口,CGlib 無此限制。
  2. 性能:在多次調用場景下,CGlib 效率更高(因避免了反射開銷)。
  3. 限制:CGlib 無法代理 final 類或 final 方法(子類無法重寫)。

五、Spring 中的選擇策略

Spring AOP 默認根據目標類是否實現接口自動選擇代理方式:

  • 若目標類實現了接口:默認使用 JDK 動態代理。
  • 若目標類未實現接口:自動切換為 CGlib 代理。

若需強制使用 CGlib(即使目標類有接口),可通過配置開啟:

  • XML 配置:<aop:aspectj-autoproxy proxy-target-class="true"/>
  • 注解配置:@EnableAspectJAutoProxy(proxyTargetClass = true)

六、使用場景建議

  1. 優先用 JDK 動態代理

    • 目標類已實現接口。
    • 追求開發便捷性(無需額外依賴)。
    • 方法調用頻率不高的場景。
  2. 選擇 CGlib

    • 目標類無接口,或需代理非接口方法。
    • 對性能要求高(如高頻調用的核心服務)。
    • 可接受引入第三方依賴。

七、總結

JDK 動態代理和 CGlib 是動態代理的兩大主流實現,各有優劣:

  • JDK 動態代理基于接口,簡單易用,是 Spring 的默認選擇。
  • CGlib 基于繼承,性能更優,適合無接口或高性能需求的場景。

理解兩者的原理和區別,有助于在實際開發中根據場景合理選擇,也能更深入地理解 Spring AOP 等框架的底層實現。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/915776.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/915776.shtml
英文地址,請注明出處:http://en.pswp.cn/news/915776.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

變頻器帶動電機:全方位解析參數變化

在現代工業自動化領域&#xff0c;變頻器作為電機調速的核心設備&#xff0c;扮演著至關重要的角色。它能夠精準地控制電機的運行狀態&#xff0c;通過改變電源頻率和電壓&#xff0c;實現電機轉速、轉矩、功率等參數的靈活調整。本文將深入探討變頻器帶動電機時&#xff0c;各…

OpenCV 入門知識:圖片展示、攝像頭捕獲、控制鼠標及其 Trackbar(滑動條)生成!

&#x1f636;?&#x1f32b;?&#x1f636;?&#x1f32b;?&#x1f636;?&#x1f32b;?&#x1f636;?&#x1f32b;?Take your time ! &#x1f636;?&#x1f32b;?&#x1f636;?&#x1f32b;?&#x1f636;?&#x1f32b;?&#x1f636;?&#x1f32b;?…

Elasticsearch是什么?

Elasticsearch&#xff08;簡稱ES&#xff09;是一種基于Lucene的分布式搜索引擎&#xff0c;廣泛應用于大數據、日志分析、全文搜索等場景。它的核心是提供高效、可擴展的搜索和分析能力。ES 提供了強大的全文搜索、聚合分析、數據可視化等功能&#xff0c;可以用來快速地對海…

(Arxiv-2025)OmniGen2:通向先進多模態生成的探索

OmniGen2&#xff1a;通向先進多模態生成的探索 paper title&#xff1a;OmniGen2: Exploration to Advanced Multimodal Generation paper是BAAI發布在Arxiv 2025的工作 Code:鏈接 Abstract 在本研究中&#xff0c;我們提出了 OmniGen2&#xff0c;這是一種多功能、開源的生成…

期權到期會對大盤有什么影響?

本文主要介紹期權到期會對大盤有什么影響&#xff1f;期權到期對大盤的影響主要體現在以下幾個方面&#xff0c;但整體影響通常有限且短期&#xff0c;具體效果需結合市場環境、期權規模及行權價位置綜合判斷。期權到期會對大盤有什么影響&#xff1f;1. 市場流動性波動到期日效…

【LeetCode刷題指南】--隨機鏈表的復制

&#x1f525;個人主頁&#xff1a;草莓熊Lotso &#x1f3ac;作者簡介&#xff1a;C研發方向學習者 &#x1f4d6;個人專欄&#xff1a; 《C語言》 《數據結構與算法》《C語言刷題集》《Leetcode刷題指南》 ??人生格言&#xff1a;生活是默默的堅持&#xff0c;毅力是永久的…

系統學習算法:專題十四 鏈表

前提知識&#xff1a;1.畫圖&#xff0c;數據結構相關的題&#xff0c;畫圖必不可少&#xff0c;只要能畫出來&#xff0c;那么后面的代碼就很容易能寫出來&#xff0c;因為將抽象的數據結構轉換為直觀的圖畫2.引入虛擬頭結點&#xff0c;也叫哨兵位&#xff0c;能夠避免考慮很…

零基礎學后端-PHP語言(第一期-PHP環境配置)

從本期開始&#xff0c;我們學習PHP&#xff0c;但是我們要先配置PHP環境 PHP官網鏈接&#xff1a;PHP For Windows: Binaries and sources Releases 我們可以看到有以下資源 可以看到有很多php的版本&#xff0c;有Non Thread Safe和Thread Safe&#xff0c;還有zip&#xf…

C++ primer知識點總結

《C Primer》系統學習指南&#xff1a;從C到C的平滑過渡根據你提供的《C Primer》目錄和你的需求&#xff08;C語言背景轉C&#xff0c;側重網絡編程&#xff09;&#xff0c;我將為你制定一個全面的學習計劃&#xff0c;包含知識點詳解、C/C對比、實戰案例和分階段項目練習。第…

異構融合 4A:重構高性能計算與復雜場景分析的安全與效率邊界

當全球數據量以每兩年翻一番的速度爆炸式增長&#xff0c;高性能計算&#xff08;HPC&#xff09;與復雜場景分析正成為破解氣候預測、基因測序、金融風控等世界級難題的關鍵引擎。但異構計算環境的碎片化、多系統協同的復雜性、數據流動的安全風險&#xff0c;正在形成制約行業…

【華為機試】240. 搜索二維矩陣 II

文章目錄240. 搜索二維矩陣 II描述示例 1示例 2提示解題思路核心分析問題轉化算法實現方法1&#xff1a;右上角開始搜索&#xff08;推薦&#xff09;方法2&#xff1a;逐行二分查找方法3&#xff1a;分治法方法4&#xff1a;左下角開始搜索復雜度分析核心要點數學證明右上角搜…

瘋狂星期四文案網第16天運營日記

網站運營第16天&#xff0c;點擊觀站&#xff1a; 瘋狂星期四 crazy-thursday.com 全網最全的瘋狂星期四文案網站 運營報告 昨日訪問量 昨日30多ip, 今天也差不多&#xff0c;同步上周下降了一些&#xff0c;感覺明天瘋狂星期四要少很多了&#xff0c;記得上周四700多ip&…

Linux系統基礎入門與配置指南

Linux基本概述與配置 一、我們為什么使用Linux&#xff08;Linux的優點&#xff09;開源與自由 免費&#xff1a; 無需支付許可費用&#xff0c;任何人都可以自由下載、安裝和使用。源代碼開放&#xff1a; 任何人都可以查看、修改和分發源代碼。這帶來了極高的透明度、安全性和…

如何刪除VSCode Marketplace中的publisher

網頁上并沒有提供刪除的按鈕&#xff0c;需要通過命令的形式刪除。 vsce delete-publisher [要刪除的名字]# 鍵入token # y 確認這里的token是之前在Azure DevOps中創建的token&#xff0c;忘了的話可以重建一個 刷新網頁看一下 成功刪除了。

Windows安裝git教程(圖文版)

Git 是一個分布式版本控制系統&#xff0c;用于跟蹤文件的變化&#xff0c;特別是在軟件開發中。它使得多個開發者可以在不同的機器上并行工作&#xff0c;然后將他們的改動合并在一起。是在開發過程中&#xff0c;經常會用到的一個工具。本章教程&#xff0c;主要介紹Windows上…

Remote Framebuffer Protocol (RFB) 詳解

RFC 6143 規范文檔&#xff1a;The Remote Framebuffer Protocol 文章目錄1. 引言2. 初始連接流程2.1 TCP連接建立2.2 協議版本協商2.3 安全握手3. 顯示協議機制3.1 核心概念3.2 像素格式4. 輸入協議4.1 鍵盤事件(KeyEvent)4.2 鼠標事件(PointerEvent)5. 協議消息詳解5.1 握手消…

從 DeepSeek-V3 到 Kimi K2:八種現代大語言模型架構設計

編譯&#xff1a;青稞社區Kimi 原文&#xff1a;https://magazine.sebastianraschka.com/p/the-big-llm-architecture-comparison 首發&#xff1a;https://mp.weixin.qq.com/s/lSM2jk1UxJVz1WllWYQ4aQ 自原始 GPT 架構開發以來已經過去了七年。乍一看&#xff0c;從 2019 年的…

linux驅動開發筆記--GPIO驅動開發

目錄 前言 一、設備樹配置 二、驅動編寫 三、用戶空間測試 總結 前言 開發平臺&#xff1a;全志A133&#xff0c;開發環境&#xff1a;linux4.9andrio10&#xff0c;開發板&#xff1a;HelperBoard A133_V2.5。 一、設備樹配置 打開板級設備樹配置文件&#xff0c;路徑&a…

騰訊iOA:企業軟件合規與安全的免費守護者

人們眼中的天才之所以卓越非凡&#xff0c;并非天資超人一等而是付出了持續不斷的努力。1萬小時的錘煉是任何人從平凡變成超凡的必要條件。———— 馬爾科姆格拉德威爾 目錄 一、為什么要使用騰訊iOA&#xff1f; 二、中小企業軟件合規痛點 三、騰訊iOA解決方案 3.1 核心技…

C#定時任務實戰指南:從基礎Timer到Hangfire高級應用

高效管理后臺作業&#xff0c;讓定時任務成為應用的可靠引擎 在C#應用開發中&#xff0c;定時任務是實現數據同步、報表生成、系統維護等后臺作業的核心技術。本文將深入探討C#生態中主流的定時任務解決方案&#xff0c;從基礎的內置Timer到強大的Quartz.NET和Hangfire框架&…