SpringBoot2.X 實(shí)戰(zhàn)6-Cache

一.Spring Cache

1.概述

Spring框架支持透明地向應(yīng)用程序添加緩存.抽象的核心是將緩存應(yīng)用于方法,從而根據(jù)緩存中可用的信息減少數(shù)據(jù)庫訪問的次數(shù).
緩存邏輯是透明地應(yīng)用的,不會對調(diào)用程序造成任何干擾.
只要通過@EnableCaching注釋啟用緩存支持,Spring Boot就會自動配置緩存基礎(chǔ)設(shè)施.

2.支持的緩存

緩存抽象不提供實(shí)際的存儲小腊,而是依賴于org.springframework.cache 和 org.springframework.cache.CacheManager 接口

  • Generic
  • JCache (JSR-107) (EhCache 3, Hazelcast, Infinispan, and others)
  • EhCache 2.x
  • Hazelcast
  • Infinispan
  • Couchbase
  • Redis
  • Caffeine
  • Simple

二.幾個重要概念:

序號 名詞 說明
01 Cache 緩存接口,定義緩存操作朴皆。實(shí)現(xiàn)有:RedisCache娩怎、EhCacheCache搔课、ConcurrentMapCache等
02 CacheManager 緩存管理器,管理各種緩存(cache)組件
03 keyGenerator 緩存數(shù)據(jù)時key生成策略
04 serialize 緩存數(shù)據(jù)時value序列化策略

三.幾個重要注解:

序號 注解 說明
01 @EnableCaching 開啟基于注解的緩存
02 @Cacheable 主要針對方法配置截亦,能夠根據(jù)方法的請求參數(shù)對其進(jìn)行緩存
03 @CachePut 保證方法被調(diào)用爬泥,又希望結(jié)果被緩存。與@Cacheable區(qū)別在于是否每次都調(diào)用方法崩瓤,常用于更新.
04 @CacheEvict 清空緩存
05 @CacheConfig 統(tǒng)一配置本類的緩存注解的屬性
06 @Caching 混合注解

四.幾個重要參數(shù):

@Cacheable/@CachePut/@CacheEvict 主要的參數(shù)

序號 參數(shù) 說明
01 value cacheNames的別名.即緩存的名稱
02 cacheNames 同value
03 key 緩存的key,支持SPEL表達(dá)式.默認(rèn)為""
04 keyGenerator key生成器,默認(rèn)使用SimpleKeyGenerator,即根據(jù)Key數(shù)組生成一個字符串
05 cacheManager cache管理器
06 cacheResolver 自定義CacheResolver的bean名稱
07 condition 滿足某個條件時執(zhí)行,支持SPEL表達(dá)式
08 unless 滿足某個條件時不執(zhí)行,支持SPEL表達(dá)式.否定緩存, 當(dāng)條件為 true 時, 就不會緩存.
09 sync 是否異步執(zhí)行
10 allEntries @CacheEvict獨(dú)有,是否清空所有的緩存
11 beforeInvocation @CacheEvict獨(dú)有,是否在方法執(zhí)行前就清空袍啡,缺省為 false,如果指定為 true却桶,則在方法還沒有執(zhí)行的時候就清空緩存境输,缺省情況下,如果方法執(zhí)行拋出異常,則不會清空緩存

五.緩存SpEL可用元數(shù)據(jù)

序號 名稱 位置 說明 舉例
01 methodName Root object 當(dāng)前被調(diào)用的方法名 #root.methodName
02 method Root object 當(dāng)前被調(diào)用的方法 #root.method.name
03 target Root object 當(dāng)前被調(diào)用的目標(biāo)對象 #root.target
04 targetClass Root object 當(dāng)前被調(diào)用的目標(biāo)對象類 #root.targetClass
05 args Root object 當(dāng)前被調(diào)用的方法的參數(shù)列表 #root.args[0]
06 caches Root object 當(dāng)前方法調(diào)用使用的緩存列表(如@Cacheable(value={“cache1”, “cache2”}))嗅剖,則有兩個cache #root.caches[0].name
07 Argument name Evaluation context 當(dāng)前被調(diào)用的方法的參數(shù)蛋逾,如findById(Long id),我們可以通過#id拿到參數(shù) #iban or #a0 (you can also use #p0 or #p<#arg> notation as an alias).
08 result Evaluation context 方法執(zhí)行后的返回值(僅當(dāng)方法執(zhí)行之后的判斷有效,如‘unless','cache evict'的beforeInvocation=false) #result

六.SpringBoot使用

1.加入依賴

使用之前需要加入以下依賴:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>

2.開啟自動配置

開啟緩存

@EnableCaching
@SpringBootApplication
public class SpringBootCacheApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootCacheApplication.class, args);
    }
}

3.使用 @Cacheable

使用 @Cacheable 注解后, 調(diào)用 findByName 會先從緩存中查找是否有對應(yīng)的數(shù)據(jù), 如果沒有才會去數(shù)據(jù)庫查找, 并將查找的結(jié)果放入緩存中.如果在緩存中查詢到數(shù)據(jù)則不會訪問方法體重的代碼.
1.方法運(yùn)行事前, 先去查詢 Cache(緩存組件),按照 cacheNames 指定的名字獲取:
(CacheManager 先獲取相應(yīng)的緩存),第一次獲取緩存如果沒有 Cache 組件會自動創(chuàng)建.
2.去 cache 中查找緩存的內(nèi)容,使用一個 key ,默認(rèn)就是方法的參數(shù):
key 是按照某種策略生成的,默認(rèn)使用的 keyGenerator生成的,默認(rèn)使用 SimpleKeyGenerator 生成 key
SimpleKeyGenerator 生成 key 的默認(rèn)策略:
如果沒有參數(shù), key = new SimpleKey()
如果只有一個參數(shù), key = 參數(shù)的值
如果有多個參數(shù), key = new SimpleKey(params)
3.沒有查詢到緩存就調(diào)用目標(biāo)方法:
4.將目標(biāo)方法返回的結(jié)果放進(jìn)緩存中.

@Cacheable
public ReturnDO<UserDetailDO> findByName(String name) {
    log.info("UserDetailService|findByName|{}", name);
    UserDetailDO userDetailDO = repository.findUserCacheDOByNameIs(name);
    return ReturnDO.<UserDetailDO>builder().data(userDetailDO).build();
}

4.使用 @CachePut

被標(biāo)注@CachePut的方法,每次方法被調(diào)用均會執(zhí)行目標(biāo)方法,并對請求參數(shù)對其結(jié)果進(jìn)行緩存,這個注解主要用于新增數(shù)據(jù)和更新數(shù)據(jù)上(POST & PUT).
這里的KEY & VALUE必須和 @Cacheable KEY & VALUE 相同.
運(yùn)行時機(jī):
1.先調(diào)用目標(biāo)方法;
2.將目標(biāo)方法的結(jié)果緩存起來;

@CachePut(key = "#result.data.name")
public ReturnDO<UserDetailDO> update(UserDetailDO userCacheDTO) {
    UserDetailDO userDetailDO = repository.save(userCacheDTO);
    return ReturnDO.<UserDetailDO>builder().data(userDetailDO).build();
}

5.使用 @CacheEvict

@CacheEvict 的作用是根據(jù)一定的條件對緩存進(jìn)行清空(DELETE),該方法也是每次調(diào)用均會執(zhí)行,刪除數(shù)據(jù)同時刪除緩存中的數(shù)據(jù)
key:指定要清除的數(shù)據(jù)
allEntries = true:指定清除這個緩存中所有的數(shù)據(jù)
beforeInvocation = true: 緩存的清除是否在方法之前執(zhí)行
默認(rèn)代表緩存清除操作是在方法執(zhí)行之后執(zhí)行:如果出現(xiàn)異常緩存就不會清除
beforeInvocation = false: 緩存的清除是否在方法之后執(zhí)行
無論方法是否出現(xiàn)異常,緩存都清除

@CacheEvict
public ResponseEntity<Void> delete(String name) {
    repository.deleteUserCacheDOByNameIs(name);
    return new ResponseEntity<>(HttpStatus.OK);
}

6.使用 @CacheConfig

方法統(tǒng)一注解,一般注解到類上,表示該類方法中相同的注解配置使用值(統(tǒng)一設(shè)置配置).

@Slf4j
@Service
@CacheConfig(cacheNames = "redis_cache")
public class UserDetailService {

7.使用 @Caching

@Caching 復(fù)雜緩存配置

@Caching(
       cacheable = {
            @Cacheable(key = "#a0.name")
       },
       put = {
            @CachePut(key = "#result.data.name"),
            @CachePut(key = "#result.data.phone")
       }
)
public ReturnDO<UserDetailDO> create(UserDetailDO userCacheDTO) {
    UserDetailDO userDetailDO = repository.save(userCacheDTO);
    return ReturnDO.<UserDetailDO>builder().data(userDetailDO).build();
}

七.整合 Redis

八.個性化Cache

1.自定義 KeyGenerator

2.自定義 RedisCacheManager 序列化方式

3.自定義緩存組件

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末窗悯,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子偷拔,更是在濱河造成了極大的恐慌蒋院,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件莲绰,死亡現(xiàn)場離奇詭異欺旧,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)蛤签,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進(jìn)店門辞友,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人震肮,你說我怎么就攤上這事称龙。” “怎么了戳晌?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵鲫尊,是天一觀的道長。 經(jīng)常有香客問我沦偎,道長疫向,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任豪嚎,我火速辦了婚禮搔驼,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘侈询。我一直安慰自己舌涨,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布妄荔。 她就那樣靜靜地躺著泼菌,像睡著了一般。 火紅的嫁衣襯著肌膚如雪啦租。 梳的紋絲不亂的頭發(fā)上哗伯,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天,我揣著相機(jī)與錄音篷角,去河邊找鬼焊刹。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的虐块。 我是一名探鬼主播俩滥,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼贺奠!你這毒婦竟也來了霜旧?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤儡率,失蹤者是張志新(化名)和其女友劉穎挂据,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體儿普,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡崎逃,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了眉孩。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片个绍。...
    茶點(diǎn)故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖浪汪,靈堂內(nèi)的尸體忽然破棺而出巴柿,到底是詐尸還是另有隱情,我是刑警寧澤吟宦,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布篮洁,位于F島的核電站,受9級特大地震影響殃姓,放射性物質(zhì)發(fā)生泄漏袁波。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一蜗侈、第九天 我趴在偏房一處隱蔽的房頂上張望篷牌。 院中可真熱鬧,春花似錦踏幻、人聲如沸枷颊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽夭苗。三九已至,卻和暖如春隔缀,著一層夾襖步出監(jiān)牢的瞬間题造,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工猾瘸, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留界赔,地道東北人丢习。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像淮悼,于是被迫代替她去往敵國和親咐低。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評論 2 353

推薦閱讀更多精彩內(nèi)容