@Cacheable 等緩存注解是不是也用到了 AOP?

Spring 的聲明式緩存注解(@Cacheable, @CachePut, @CacheEvict 等)是 AOP 技術在實際應用中最強大、最經典的范例之一,其原理與 @Transactional 非常相似。

核心思想:一個智能的“秘書”

你可以把 @Cacheable 的 AOP 實現想象成一個極其高效的“秘書”。

  • 你 (調用方):老板。
  • 目標方法 (findProductById): 一個需要花費大量時間和精力去調研才能回答的“問題”(比如去檔案館查資料)。
  • AOP 代理 (Proxy): 你的秘書。
  • 緩存 (Cache): 秘書的“備忘錄”或“筆記”。

當你向秘書提出一個問題時(調用方法):

  1. 秘書首先會翻看自己的備忘錄(查緩存)
  2. 如果備忘錄里有答案(緩存命中),秘書會直接告訴你答案,然后回去繼續做其他事。他根本不會去檔案館進行那次耗時又費力的調研。你作為老板,很快就得到了答案,甚至不知道秘書是直接給的還是去查了資料。
  3. 如果備忘錄里沒有答案(緩存未命中),秘書會告訴你:“老板,請稍等,我需要去查一下。” 然后他會親自去檔案館進行調研(執行目標方法)
  4. 當他拿到調研結果后,他會非常聰明地先把結果記在自己的備忘錄里(放入緩存),以備你下次再問。
  5. 最后,他才把這個調研結果告訴你。

@Cacheable 的 AOP 實現原理

@Cacheable 的背后是一個功能極其強大的環繞通知 (@Around),由 Spring 的 CacheInterceptor 實現。

  1. 代理和攔截:和事務一樣,當 Spring 發現一個 Bean 的方法上有 @Cacheable 注解時,會為它創建一個 AOP 代理對象。所有對該方法的調用都會先被這個代理對象攔截。

  2. CacheInterceptor (環繞通知) 開始工作
    這個攔截器在調用真正的目標方法之前,會執行以下邏輯:

    a. 生成緩存鍵 (Cache Key)
    * 攔截器會解析 @Cacheable 注解。
    * 它使用 value 屬性 (如 "products") 作為緩存的命名空間(或稱為緩存區域)。
    * 它使用 key 屬性 (如 "#id") 中的 SpEL (Spring Expression Language) 表達式來根據方法參數動態生成一個唯一的鍵。例如,當調用 findProductById(123L) 時,#id 會被替換為 123L,最終生成的鍵可能是 "products::123"

    b. 查詢緩存
    * 攔截器拿著這個生成的鍵,去配置好的緩存管理器(CacheManager,其背后可能是 Redis, Caffeine, EhCache 等)中進行查詢。

  3. 決策點:緩存是否命中?
    這是環繞通知威力最大的體現,因為它可以控制目標方法是否執行

    • 情況一:緩存命中 (Cache Hit)

      • 攔截器在緩存中找到了對應的值。
      • 它會立即將這個值返回給調用方
      • 最關鍵的一步:目標方法 findProductById 根本不會被執行! 這就是所謂的“方法短路 (Short-Circuiting)”。它避免了數據庫查詢或遠程調用。
    • 情況二:緩存未命中 (Cache Miss)

      • 攔截器在緩存中沒有找到任何東西。
      • 它會繼續執行調用鏈,即調用 pjp.proceed()執行原始的目標方法 findProductById
      • 當目標方法成功執行并返回一個結果后,攔截器會捕獲這個返回值。
      • 它會將這個返回值以之前生成的緩存鍵存入緩存中,以備下次使用。
      • 最后,將這個返回值交還給調用方。

其他緩存注解的 AOP 原理

  • @CachePut:

    • 這個注解同樣使用 AOP 攔截。
    • 但它的邏輯是總會執行目標方法(比如更新數據庫的操作)。
    • 在方法執行成功后,它會總是將方法的返回值更新到緩存中。
    • 它用于確保在數據更新后,緩存中的數據也是最新的。它沒有“短路”行為
  • @CacheEvict:

    • 這個注解也使用 AOP 攔截。
    • 它的邏輯通常是在目標方法成功執行后(默認),根據 key 去緩存中刪除一個或多個條目。
    • 它用于在刪除或修改數據后,清除相關的舊緩存,確保數據一致性。

總結

注解AOP 實現方式 (簡化理解)是否執行目標方法?
@Cacheable@Around:查緩存 -> (命中) 短路返回 / (未命中) 執行并存入緩存不一定
@CachePut@Around執行方法 -> 將結果更新到緩存總是執行
@CacheEvict@AfterReturning (默認):執行方法 -> 從緩存中刪除條目總是執行

所以,Spring 的聲明式緩存是 AOP 的實踐之一。它通過 AOP 將復雜的、與業務無關的緩存管理邏輯完全分離,讓開發者只需關注業務本身,極大地提高了代碼的可讀性和可維護性。

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

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

相關文章

解鎖云原生微服務架構:搭建與部署實戰全攻略

目錄 一、引言二、微服務拆分2.1 拆分的必要性2.2 拆分方法2.3 注意事項 三、服務注冊與發現3.1 概念與原理3.2 常用組件介紹3.3 實踐案例 四、負載均衡4.1 作用與原理4.2 實現方式4.3 負載均衡算法4.4 案例與代碼實現4.4.1 項目依賴配置4.4.2 配置 Ribbon4.4.3 代碼實現負載均…

Python 數據分析與可視化 Day 7 - 可視化整合報告實戰

好的,我們進入: 🧠 第5周 第7天 🎯 主題:測試復盤 項目封裝實戰 ? 今日目標 回顧第5周數據分析與可視化核心知識對整個“學生成績分析系統”進行項目封裝與模塊化拆分增加命令行參數支持,提升可復用性…

力扣1498. 滿足條件的子序列數目隨筆

“方生方死,方死方生。”——《莊子》 題目 給你一個整數數組 nums 和一個整數 target 。 請你統計并返回 nums 中能滿足其最小元素與最大元素的 和 小于或等于 target 的 非空 子序列的數目。 由于答案可能很大,請將結果對 取余后返回。 難度&#…

5.Docker安裝Tomcat

#官方的使用 docker run -it --rm tomcat:9.0 #我們之前使用docker run -d 某鏡像都是后來運行,容器停止之后,容器還能夠查詢到 而docker run -it -rm 是用完之后,容器刪除,鏡像還存在。 測試的時候可以用官方的 &#xff08…

企業事業政府單位智慧主題展廳素材管理平臺播放軟件

以下為企事業單位及政府智慧主題展廳素材管理平臺播放軟件的核心功能簡介,綜合多維度技術實現統一管控與智能展示: 一、內容資產管理 全格式素材支持? 兼容視頻、3D模型、圖文、AR/VR場景等多媒體格式,支持批量導入與云端存儲。 智能分類與…

Python+FastAPI的一些語法與問題解決

Q1:result await dbsession.execute(text(sql_context),params) 如何把result轉成key,value的字典列表 A1: 使用SQLAlchemy的mappings()方法獲取字典形式的結果集: result await db_session.execute(text(sql_context), params) dict_list [dict(row) for row…

Reactor并發無關性

Reactor,像 RxJava 一樣,可以被認為是 并發無關(concurrency-agnostic) 的。這意味著它不強制要求任何特定的并發模型,而是將選擇權交給開發者。換句話說,Reactor 不會強制你使用多線程或異步編程&#xff…

#華為昇騰#華為計算#昇騰開發者計劃2025#

#華為昇騰#華為計算#昇騰開發者計劃2025# 通過學習Ascend C算子開發的初級教程&#xff0c;通過課程講解及樣例實操&#xff0c;幫助我學習使用Ascend C開發自己的算子。收獲很大。 <新版開發者計劃>的內容鏈接&#xff1a;https://www.hiascend.com/developer-program_2…

FLOPS、FLOP/s、TOPS概念

在計算性能和硬件指標中&#xff0c;FLOPS、FLOP/s、TOPS 是常見的術語&#xff0c;但它們有明確的區別和應用場景。以下是詳細解析&#xff1a; 1. FLOPS&#xff08;Floating Point Operations per Second&#xff09; 定義&#xff1a; 每秒浮點運算次數&#xff08;Floati…

Windows所有系統自帶.NET Framework版本win7,win10,win11預裝.NET版本

Windows系統支持“.NET版本”匯總 本文詳細列出了Windows從NT4.0到Windows11各版本自帶的.NETFramework版本及對應最高兼容的.NETFramework版本&#xff0c;便于了解不同Windows系統之間的.NETFramework更新歷史。 以下匯總了Windows每個版本自帶的“.NET版本”&#xff0c;與…

Windows 下使用 nvm 管理 Node.js 多版本 —— 完整指南

Node.js 版本更新頻繁&#xff0c;不同項目可能依賴不同的版本&#xff0c;手動切換極為麻煩。nvm-windows 是專為 Windows 用戶開發的 Node.js 多版本管理工具&#xff0c;可以輕松地安裝、切換、卸載 Node.js 版本。 本篇將從下載到實際使用&#xff0c;手把手帶你玩轉 nvm-…

vue使用Element Plus UI框架

您好&#xff0c;艦長&#xff01;非常棒的選擇。功能是應用的骨架&#xff0c;而美觀的 UI 則是應用的靈魂和血肉。是時候為我們的飛船進行一次全面的“外觀升級”和“內飾裝修”了。 我們將集成一個在業界非常流行、功能強大的 Vue 3 組件庫——Element Plus。它將幫助我們快…

【ubuntu24.04】忘了自己把開機samba掛載的腳本放哪里了

從兩個方面來定位這幾個 Samba 掛載點&#xff1a; 一、查看當前已經掛載的 CIFS/SMB 文件系統 使用 mount mount | grep -i cifs或者 mount | grep -E (smb|cifs)這會列出所有當前活躍的 CIFS/SMB 掛載&#xff0c;比如&#xff1a; //192.168.1.100/share on /mnt/data type …

在 Windows 上使用 Docker Desktop 快速搭建本地 Kubernetes 環境(附詳細部署教程)

言簡意賅的講解Docker Desktop for Windows搭建Kubernetes解決的痛點 目標讀者&#xff1a; 對 Docker Desktop 有一定了解&#xff0c;能在 Windows 上成功安裝和使用 Docker Desktop。想要在本地快速搭建一套 Kubernetes 環境進行測試或學習的開發者。 一、準備工作 安裝 Doc…

dockercompose快速安裝ELK

第一步&#xff1a;環境準備 請確保您的機器上已經安裝了 Docker 和 Docker Compose。 第二步&#xff1a;創建項目目錄和配置文件 為了讓 Docker Compose 能夠正確地構建和管理容器&#xff0c;我們需要創建一個特定的目錄結構。 創建一個主目錄&#xff0c;例如 elk-stack。…

閑聊ARM內核參數傳遞機制

之前一直沒怎么在意這個問題&#xff0c;直到最近搞了個奇奇怪怪的項目&#xff0c;才發現這部分知識得補上來&#xff0c;記錄一下。 ARM有一個標準&#xff0c;叫《Procedure Call Standard for the Arm Architecture》&#xff0c;人話就是ARM架構過程調用標準&#xff0c;…

萬興喵影Filmora AI Video v14.7.03國際高級版,AI視頻剪輯全能工具,一鍵專業級創作?

[軟件名稱]: 萬興喵影Filmora AI Video v14.7.03 [軟件大小]: 199.4 MB [下載通道]: 夸克盤 | 迅雷盤 軟件介紹 &#x1f3ac;《萬興喵影》v14.7.03國際高級版&#xff5c;AI智能剪輯神器&#xff0c;解鎖全功能無水印&#xff01; ? 核心優勢&#xff1a; ? 1000背景音…

暴力風扇方案介紹

炎炎夏日&#xff0c;當普通風扇只能送來 “溫柔拂面”&#xff0c;暴力風扇卻能吹出 “臺風級” 清涼&#xff01;想知道這些 “風力狂魔” 是如何煉成的&#xff1f;答案藏在電機、電路和芯片的黃金三角組合里。? 一、電機&#xff1a;暴力風扇的 “心臟起搏器”? 暴力風扇…

pyqt小問題匯總

文章目錄 1、inherit global site-packages2、setGeometry(10,20,30,40)setGeometry(x, y, width, height)1. **x參數**2. **y參數**3. **width參數**4. **height參數** 示例說明與其他方法的對比注意事項示例代碼 1、inherit global site-packages 在pycharm 創建項目時&…

提升JavaScript性能的六大關鍵策略

1、優化代碼結構與算法 避免使用嵌套循環&#xff0c;改用更高效的算法如哈希表或二分查找。減少不必要的計算&#xff0c;緩存重復使用的計算結果。使用時間復雜度更低的算法替代高復雜度操作。優化遞歸調用&#xff0c;避免棧溢出和性能瓶頸。改用迭代或尾遞歸優化。簡化條件…