Spring註解快取設計原理及實戰

2021-10-18 23:00:36 字數 2862 閱讀 2464

spring 3.1後引入註解快取,其本質不是乙個具體的快取實現,而是乙個對快取使用的抽象。

通過在既有**中新增少量自定義註解,即可夠達到使用快取物件和快取方法的返回物件的效果。

spring的快取技術具備相當的靈活性,不僅能夠使用spel來定義快取的key和各種condition,還提供開箱即用的快取臨時儲存方案,也支援和主流的專業快取整合。

spring cache的關鍵原理就是spring aop,通過spring aop實現了在方法呼叫前、呼叫後獲取方法的入參和返回值,進而實現了快取的邏輯。而spring cache利用了spring aop的動態**技術,即當客戶端嘗試呼叫pojo的foo()方法的時候,給它的不是pojo自身的引用,而是乙個動態生成的**類

spring cache主要使用如下註解

主要針對方法上註解使用,部分場景也可類上註解。當在類上使用時,該類所有方法都將受影響。

作用和配置方法表:

標籤型別

作用主要配置引數說明

@cacheable

主要針對方法配置,能夠根據方法的請求引數對其結果進行快取

value:快取的名稱,在 spring 配置檔案中定義,必須指定至少乙個

key:快取的 key,可為null,若指定要按 spel 表示式編寫,若不指定,則預設按方法的所有引數進行組合

condition:快取的條件,可為null,使用 spel 編寫,返回 true 或者 false,為 true 時才進行快取

@cacheput

主要針對方法配置,能夠根據方法的請求引數對其結果進行快取,和 @cacheable 不同的是,它每次都會觸發真實方法的呼叫

同上@cacheevict

主要針對方法配置,能夠根據一定的條件對快取進行清空

同上。

allentries:是否清空所有快取內容,預設為 false,如果指定為 true,則方法呼叫後將立即清空所有快取;

beforeinvocation:是否在方法執行前就清空,預設為 false,如果指定為 true,則在方法還沒有執行的時候就清空快取,預設情況下,如果方法執行丟擲異常,則不會清空快取

spring註解能滿足一般應用對快取的需求,但隨著應用服務的複雜化,大併發高可用性能要求下,需要進行一定的擴充套件,這時對其自身整合的快取方案可能不太適用,該怎麼辦?

這能滿足一般應用的快取需求,但當使用者量上去或效能跟不上,總需要進行擴充套件,這時你或許對其提供的記憶體快取不滿意了,因為其不支援高可用,也不持久化。這時就需要自定義你快取方案了,spring也想到了這點。

先不考慮如何持久化快取,畢竟這種三方實現很多,要考慮的是,怎麼利用spring提供的擴充套件點實現我們自己的快取,且在不改原來已有**的情況下進行擴充套件,是否在方法執行前就清空,預設為false,如果指定為true,則在方法還沒有執行的時候就清空快取,預設情況下,如果方法執行丟擲異常,則不會清空快取。

三步:

註解快取的使用,可有效增強**可讀性,同時統一管理快取,提供較好的可擴充套件性。

為此,酒店商家端在spring註解快取基礎上,自定義了適合自身業務特性的註解快取。

主要使用兩個標籤,即**@hotelcacheable**、@hotelcacheevict,其作用和配置方法見下表:

標籤型別

作用主要配置引數說明

@hotelcacheable

主要針對方法配置,能夠根據方法的請求引數對其結果進行快取

domain作用域,針對集合場景,解決批量更新問題;domainkey作用域對應的快取key;key快取物件key 字首;fieldkey快取物件key,與字首合併生成物件key;condition快取獲取前置條件,支援spel語法;cachecondition快取刷入前置條件,支援spel語法;expiretime超時時間設定

@hotelcacheevict

主要針對方法配置,能夠根據一定的條件對快取進行清空

同上

增加作用域的概念,解決商家資訊變更下,多重重要資訊實時更新的問題。

增加cachecondition快取刷入前置判斷,有效解決商家業務多重外部依賴場景下,業務降級有損服務下,業務資料一致性保證,不因為快取的增加影響業務的準確性;自定義cachemanager快取管理器,可以有效相容公共基礎元件medis、cellar相關服務,在對應用程式不做改動的情況下,有效切換快取方式;同時,統一的快取服務aop入口,結合接入mtconfig統一配置管理,對應用內快取做好降級準備,一鍵關閉快取。

spring cache的原理是基於動態生成的proxy**機制來進行切面處理,關鍵點是物件的引用問題,如果物件的方法是類裡面的內部呼叫(this引用)而不是外部引用的場景下,會導致proxy失敗,那麼我們所做的快取切面處理也就失效了。因此,應避免已註解快取的方法在類裡面的內部呼叫。

使用的key約束,快取的key應盡量使用簡單的可區別的元素,如id、名稱等,不能使用list等容器的值,或者使用整體model物件的值。非public方法無法使用註解快取實現。

註解驅動的spring cache能夠極大的減少我們編寫常見快取的**量,通過少量的注釋標籤和配置檔案,即可達到使**具備快取的能力,且具備很好的靈活性和擴充套件性。但是我們也應該看到,spring cache由於基於spring aop技術,尤其是動態的proxy技術,導致其不能很好的支援方法的內部呼叫或者非public方法的快取設定,當然這些都是可以解決的問題。

參考

Spring快取註解

快取註解有以下三個 cacheable cacheevict cacheput 1 cacheable value accountcache 這個注釋的意思是,當呼叫這個方法的時候,會從乙個名叫 accountcache 的快取中查詢,如果沒有,則執行實際的方法 即查詢資料庫 並將執行的結果存入快取...

Spring快取註解

spring從3.1開始定義了org.springframework.cache.cache和org.springframework.cache.cachemanager介面來統一不同的快取技術,並支援jcache jsr 107 註解簡化開發 當配置上redis之後快取註解就會將快取內容儲存在re...

Spring快取註解 Cacheable

cacheable可以標記在乙個方法上,也可以標記在乙個類上。當標記在乙個方法上時表示該方法是支援快取的,當標記在乙個類上時則表示該類所有的方法都是支援快取的。對於乙個支援快取的方法,spring會在其被呼叫後將其返回值快取起來,以保證下次利用同樣的引數來執行該方法時可以直接從快取中獲取結果,而不需...