一、序言
Spring Cache是Spring體系下標準化快取框架。Spring Cache有如下優勢:
- 快取品種多
支援快取品種多,常見快取Redis、EhCache、Caffeine均支援。它們之間既能獨立使用,也能組合使用。
- 平滑遷移
Spring內部支援的快取,可實現無縫平滑遷移,無需修改業務邏輯。註解快取的實現依賴於動態代理。
大多數情況下使用的是註解版、少數情況下也能使用程式設計版。註解版與業務程式碼高度解藕,因其依託動態代理技術實現,使用場景上有一定的限制。程式設計版嵌入業務程式碼,程式碼順序執行,無前置使用條件。
二、基本概念
(一)核心概念
一個應用可以有多個快取管理器,每個快取管理器可以有多個快取,每個快取可以儲存多條記錄。
1、快取管理器
快取的儲存介質不同、快取連線不同的資料庫、快取值序列化等由快取管理器配置。快取管理器有主次之分,預設情況下使用主(首要)快取管理器。
當服務內只有一個CacheManager時,預設使用此快取管理器;當超過一個快取管理器時,需要使用Primary
註解指定預設快取管理器。
2、快取
Cache是一組配置相同快取的集合,可以理解為名稱空間,Spring Cache體系下的快取生命時間是以Cache為單位的,不支援以Key為單位設定生存時間。不同的業務對應不同的快取配置,應在快取處予以區分。
CacheName應具有顯著的業務區分度以及過期時間區分度,並且以全域性常量的方式提供,採取集中化管理的方式,禁止採用魔術變數的方式指定CacheName。
(二)補充內容
一般來說快取的Key與Value均是String型別,特別是Value通常序列化成JSON串。
三、註解版
用於基於註解的方式來管理快取資料。註解快取有如下優勢:
- 高度解藕
使用註解來實現快取,與業務高度解藕。
- 靈活管理
通過全域性配置,不修改快取邏輯,可實現如下效果:
開發環境下,可禁用快取,將流量打入資料庫,儘早的暴露可能存在的效能瓶頸;測試環境開啟快取,進行壓力測試等。
(一)動態代理
Spring Cache快取註解版的原理以及快取配置失敗的典型案例。
1、CGLib動態代理
快取的實現底層技術支援是CGLib動態代理,在目標方法呼叫前、後分別追加相應的快取操作,以達到新增快取、更新快取、刪除快取的操作。
如果註解快取配置未生效,檢查目標呼叫方法是否被動態代理。
2、配置失效
配置失效是指儘管配置了快取註解,但快取仍然未生效。
- final類與final方法
final類與final方法不滿足CGLib動態代理的條件,因此快取配置會失效。
- 內部呼叫
使用依賴注入的方式呼叫配置快取的方法生效,方法間內部呼叫不生效。
- 非public方法
非public方法配置快取不生效。
(二)常用註解
1、配置註解
(1)EnableCaching
標註於SpringBoot應用啟動類上,新增此註解表示開啟Spring Cache快取;移除表示關閉快取。如果在全域性配置檔案中新增如下配置,即使在啟動類上標註EnableCaching註解,Spring Cache快取然後是關閉狀態。
spring:
cache:
type: none
如果應用中自定義獨立於Spring容器的快取,則不受此配置影響。
(2)CacheConfig
標註於類上,更具體的說是標註於業務服務類上。統一配置如下引數資訊:
引數 | 含義 | 使用說明 |
---|---|---|
cacheManager |
快取管理器 | 預設指首要的CacheManager |
cacheNames |
快取名 | |
keyGenerator |
key值生成器 |
在類上統一進行配置,類下的方法自動繼承相應的配置。
2、快取註解
(1)Cacheable
新增快取的核心註解,分兩種情況:一是對應key值未有快取資料,先執行方法,然後根據condition和unless條件決定是否新增快取;二是對應key值已有快取,不執行方法體,直接返回資料。
引數keyGenerator
與key
是互斥的,當key
存在時keyGenerator
配置自動失效。
- 基礎引數
引數 | 含義 | 使用說明 |
---|---|---|
cacheManager |
快取管理器 | 預設指首要的CacheManager |
cacheNames |
快取名 | |
keyGenerator |
key值生成器 | |
key |
key值 |
- 高階引數
引數 | 含義 | 預設值 | 使用說明 |
---|---|---|---|
condition |
快取條件 | 指示滿足條件方執行快取操作,一般使用引數作為條件 | |
unless |
否定快取 | 當條件為 true ,方法的返回值不會被快取 | |
sync |
同步狀態 | false | 表示將方法執行結果以何種方式存入快取 |
(2)CachePut
更新快取註解。不管對應key值是否有快取資料,都執行。
- 基礎引數
引數 | 含義 | 使用說明 |
---|---|---|
cacheManager |
快取管理器 | 預設指首要的CacheManager |
cacheNames |
快取名 | |
keyGenerator |
key值生成器 | |
key |
key值 |
- 高階引數
引數 | 含義 | 使用說明 |
---|---|---|
condition |
快取條件 | 指示滿足條件方執行快取操作,一般使用引數作為條件 |
unless |
否定快取 | 當條件為 true ,方法的返回值不會被快取 |
(3)CacheEvict
主動清除快取註解。
- 基礎引數
引數 | 含義 | 使用說明 |
---|---|---|
cacheManager |
快取管理器 | 預設指首要的CacheManager |
cacheNames |
快取名 | |
keyGenerator |
key值生成器 | |
key |
key值 |
- 高階引數
引數 | 含義 | 預設值 | 使用說明 |
---|---|---|---|
condition |
快取條件 | 指示滿足條件方執行快取操作,一般使用引數作為條件 | |
allEntries |
所有快取 | false | 表示是否清空當前CacheName對應的所有快取 |
beforeInvocation |
呼叫前 | false | 表示是否在方法呼叫前清空快取 |
3、KeyGenerator
預設情況下使用SimpleKeyGenerator鍵值生成器,當不指定key值時,根據生成器規則,將方法引數轉化為快取Key值。