快取技術是一個讓所有開發人員又愛又恨的技術,我們愛快取是因為快取能給我們帶來數量級的回應和流量,但是最迷人的反而最危險,如果快取用不好也是災難級別的,特別是一些涉及到公司主要現金流的業務,如果因為我們使用快取不當,而帶給公司一定的損失,不亞于刪庫跑路的那個大兄弟,那今天我們就來看一下springboot的快取都有那些東西,學習嘛,一點點的來,慢慢積累自己的經驗,才能厚積薄發
個人公眾號:Java架構師聯盟,每日更新技術好文
# 一、JSR107快取規范
為了快取開發規范的統一,以及提升系統的擴展性,J2EE發布了JSR107快取規范,
主要是Java Caching定義了5個介面,分別是**CachingProvider、CacheManager、Cache、Entry、Expiry,**
下面我們分開詳細的展開看一下
- **CachingProvider:**
- 可以創建、配置、獲取、管理和控制多個CacheManager,一個Application在運行期間可以訪問多個CachingProvider,
- **CacheManager:**
- 可以創建、配置、獲取、管理和控制多個唯一命名的Cache,這些Cache存在于CacheManager的背景關系中,一個CacheManager僅被一個CachingProvider所擁有,
- **Cache:**
- 是一個類似于Map的資料結構并臨時存盤以Key為索引的值,一個Cache僅被一個CacheManager所擁有,
- **Entry:**
- 是存盤在Cache中的Key-Value對,
- **Expiry:**
- 每一個快取在Cache中的條目有一個定義的有效期,一旦超過這個時間,該條目就為過期狀態,一旦過期,條目將不可訪問、更新和洗掉,其中快取的有效期可以通過ExpiryPolicy設定,
-
如果說這樣講解讓你有點蒙圈的話,那沒關系,我們看下面這張圖

簡單總結一下就是:一個應用里面可以有多個快取提供者(CachingProvider),一個快取提供者可以獲取到多個快取管理器(CacheManager),一個快取管理器管理著不同的快取(Cache),快取中是一個個的快取鍵值對(Entry),每個entry都有一個有效期(Expiry),快取管理器和快取之間的關系有點類似于資料庫中連接池和連接的關系,
# 二、SpringBoot快取抽象
在我自己看來,沒有原始碼所有的理論講解,都是空談,或者說就是扯淡,所以我們來看一下,快取的原始碼級操作
Spring從3.1版本開始定義了**org.springframework.cache.CacheManager**和**org.springframework.cache.Cache**介面來統一不同的快取技術,并支持使用JSR-107注解簡化開發,
在IDEA中,使用Spring Initializr快速創建Spring Boot專案時,勾選中Cache后,在組態檔中配置debug=true,可以查看Spring Boot的自動配置項,
其中關于快取的配置類如下:
```
org.springframework.boot.autoconfigure.cache.GenericCacheConfiguration
org.springframework.boot.autoconfigure.cache.JCacheCacheConfiguration
org.springframework.boot.autoconfigure.cache.EhCacheCacheConfiguration
org.springframework.boot.autoconfigure.cache.HazelcastCacheConfiguration
org.springframework.boot.autoconfigure.cache.InfinispanCacheConfiguration
org.springframework.boot.autoconfigure.cache.CouchbaseCacheConfiguration
org.springframework.boot.autoconfigure.cache.RedisCacheConfiguration
org.springframework.boot.autoconfigure.cache.CaffeineCacheConfiguration
org.springframework.boot.autoconfigure.cache.GuavaCacheConfiguration
org.springframework.boot.autoconfigure.cache.SimpleCacheConfiguration
org.springframework.boot.autoconfigure.cache.NoOpCacheConfiguration
```
啟動專案后,可以在控制臺看到匹配到的只有SimpleCacheConfiguration這個自動配置類,而在SimpleCacheConfiguration類中,使用@Bean注解給容器中注冊了一個CacheManager,由此可看Spring Boot默認的CacheManager是ConcurrentMapCacheManager,
```
SimpleCacheConfiguration matched:
- Cache org.springframework.boot.autoconfigure.cache.SimpleCacheConfiguration automatic cache type (CacheCondition)
- @ConditionalOnMissingBean (types: org.springframework.cache.CacheManager; SearchStrategy: all) did not find any beans (OnBeanCondition)
```
同樣的,我們通過一張圖形象的展示一下看看

幾個重要概念和快取注解:

進入@Caching的原始碼可以看到,在組合注解內可以使用cacheable、put、evict
```
public @interface Caching {
Cacheable[] cacheable() default {};
CachePut[] put() default {};
CacheEvict[] evict() default {};
}
```
**@Caching的使用**
```
@Caching(
cacheable = {
@Cacheable(key = "#name")
},
put = {
@CachePut(key = "#result.id"),
@CachePut(key = "#result.cNo")
}
)
```
# @Cacheable、@CachePut、@CacheEvict中的主要引數
**key**
```
#快取的key,可以為空,也可以使用SpEL運算式撰寫
例:@Cacheable(value=https://www.cnblogs.com/biwz/archive/2020/12/05/“stu”,key=“userName”)
```
**condition**
```
#快取的條件,可以為空,也可以使用SpEL運算式撰寫,只有為true才快取/清除快取,
#不管方法執行前后都可以判斷
例:@Cacheable(value=https://www.cnblogs.com/biwz/archive/2020/12/05/“stu”,condition=“userName.length()>2”)
```
**unless**
```
#用于否定快取,只在方法執行之后判斷,也可以使用SpEL運算式撰寫
#true不快取,false才快取
例:@Cacheable(value=https://www.cnblogs.com/biwz/archive/2020/12/05/“stu”,unless=“userName == null”)
```
- **@Cacheable**
- 標注的方法執行之前,先查看快取中有沒有這個資料,默認按照引數的值作為key去快取中查找,如果沒有就運行這個方法并將方法的執行結果放入快取中,之后再呼叫該方法時,直接使用快取中的資料即可,
- **@CachePut**
- 標注的方法必須要執行,它的運行時機是,先呼叫目標方法,然后將目標方法的結果放入快取中,但是更新快取中的資料時,要注意key值,否則快取中的資料無法更新,
- **@CacheEvict**
- 這個注解中allEntries = true代表要清除某個快取中的所有資料,beforeInvocation = false代表快取的清除在方法執行之后執行,如果出現例外等情況,則不會清除快取中的資料,這是**@CacheEvict**
- 注解默認的,beforeInvocation = true代表快取的清除在方法執行之前執行,出現例外等情況,也會清除快取中的資料,
- **key的生成策略**
- key的生成默認使用SimpleKeyGenerator生成的,而SimpleKeyGenerator的生成策略有:如果沒有引數:key=new SimpleKey();如果有一個引數:key=引數的值如果有多個引數:key=new SimpleKey(params);
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/230517.html
標籤:其他
