Spring Boot中的EnableCaching簡(jiǎn)述

spring boot中自帶有數(shù)據(jù)緩存機(jī)制酥宴,主要通過(guò)其org.springframework.cache包下的各種類來(lái)實(shí)現(xiàn)啦吧。

EnableCaching

@EnableCaching是啟用緩存的注解,標(biāo)注在任何一個(gè)可自動(dòng)注入的類上即可開(kāi)啟拙寡。

Cacheable

@Cacheable是一個(gè)標(biāo)注與類與方法上的注解授滓,用于表示此類或此方法需要使用緩存機(jī)制。當(dāng)類與方法上都有時(shí),采用?就近原則褒墨。

在@Cacheable注解中,有一些常用參數(shù)可以進(jìn)行配置:

value與cacheNames?- 表示綁定的緩存名稱擎宝。這里的緩存指的是單個(gè)的緩存存儲(chǔ)器郁妈,并不是最終的鍵值對(duì)緩存對(duì)象。

key?- 表示緩存對(duì)象的?key绍申,這個(gè)才是最終的緩存鍵值對(duì)的?key噩咪。這里的參數(shù)需要使用?SpEL表達(dá)式。

keyGenerator?- 表示用于生成此方法?緩存key的類极阅。與key參數(shù)只能選擇一個(gè)添加胃碾,否則會(huì)拋出IllegalStateException異常。

cacheManager?- 指定緩存管理器筋搏。這個(gè)后面再細(xì)說(shuō)仆百。

condition?- 緩存的條件。支持SpEL奔脐,當(dāng)緩存條件滿足時(shí)俄周,才會(huì)進(jìn)入緩存取值模式。

unless?- 排除的條件髓迎。支持SpEL峦朗,當(dāng)排除的條件滿足時(shí),會(huì)直接調(diào)用方法取值排龄。

sync?- 異步緩存模式波势。是否采用異步的方式,在方法取值時(shí)異步緩存橄维。默認(rèn)false尺铣,在緩存完成后才返回值份氧。

一般情況下桑驱,可以這樣使用:

@RestController

@RequestMapping("cache")

@Cacheable(value = "cache", sync = true)

public class CacheController {

? ? @Cacheable(value = "hello", sync = true, keyGenerator = "myKeyGenerator")

? ? @GetMapping("hello")

? ? public String hello(String name) {

? ? ? ? System.out.println("name - " + name);

? ? ? ? return "hello " + name;

? ? }

? ? @GetMapping("hello2")

? ? public String hello2(@RequestParam(defaultValue = "1") Integer size, @RequestParam(defaultValue = "world") String name) {

? ? ? ? System.out.println("name - " + name);

? ? ? ? return "hello " + name;

? ? }

}


這里的CacheController被標(biāo)記上了@Cacheable(value = "cache", sync = true)收捣,表示其下的方法默認(rèn)使用名為cache的緩存存取器诀黍,并采用異步的方式進(jìn)行緩存處理闺魏。

hello方法上同樣添加了@Cacheable(value = "hello", sync = true, keyGenerator = "myKeyGenerator")姑躲,使得hello方法使用了獨(dú)立的緩存設(shè)置箫老,并通過(guò)myKeyGenerator的策略來(lái)生成?緩存key逞怨。

CachePut

將方法返回值存入到緩存中福澡,一般情況下是用在更新操作中,并于Cacheable與CacheEvict配合使用糯累。

CacheEvict

清除緩存值册踩,一般用在刪除或更新操作中暂吉,并于Cacheable與CachePut配合使用。

并且在CacheEvict注解中阎肝,多了兩個(gè)參數(shù):

allEntries?- 清除當(dāng)前value下的所有緩存风题。

beforeInvocation?- 在方法執(zhí)行前清除緩存嫉父。

示例代碼示例如下:

@Cacheable(value = "c", key = "123")

? ? @GetMapping("hello")

? ? public String hello(String name) {

? ? ? ? System.out.println("name - " + name);

? ? ? ? return "hello " + name;

? ? }

? ? @GetMapping("/put")

? ? @CachePut(value = "c", key = "123")

? ? public String put() {

? ? ? ? return "hello put";

? ? }

? ? @GetMapping("/evict")

? ? @CacheEvict(value = "c", key = "123")

? ? public String evict() {

? ? ? ? return "hello put";

? ? }

上述代碼中稽鞭,訪問(wèn)hello接口時(shí)引镊,會(huì)從c緩存存取器中取出key為123的緩存數(shù)值,沒(méi)有則會(huì)調(diào)用方法并進(jìn)行緩存吩抓。

訪問(wèn)put接口時(shí)疹娶,會(huì)將c緩存存取器key為123的緩存值改為hello put伦连,沒(méi)有則進(jìn)行緩存惑淳。

訪問(wèn)evict接口時(shí),會(huì)將c緩存存取器key為123的緩存值刪除移斩,此時(shí)訪問(wèn)hello接口會(huì)重新調(diào)用方法并進(jìn)行緩存向瓷。

CacheConfig

@CacheConfig作為類上的注解,目的是為了統(tǒng)一配置其下的方法緩存參數(shù)你稚,并設(shè)定共享緩存名入宦。

cacheNames?- 共享緩存名數(shù)組室琢。設(shè)定后表示此類下的方法緩存會(huì)依次從這些緩存存取器中取值落追,如果有轿钠,則取用緩存值;若沒(méi)有則調(diào)用方法取值症汹,并緩存值到設(shè)定的所有緩存存取器中背镇。

CacheManager

緩存管理器接口泽裳,用來(lái)做緩存管理的類。一般我們需要自定義緩存策略時(shí)胸囱,就是從CacheManager來(lái)入手的烹笔。

直接上實(shí)例:

@Component

public class MyCacheManager implements CacheManager, InitializingBean {

? ? private final Map<String, Cache> cacheMap;

? ? public MyCacheManager() {

? ? ? ? cacheMap = new HashMap<>();

? ? }

? ? @Override

? ? public Cache getCache(String name) {

? ? ? ? System.out.println("正在獲取緩存 - " + name);

? ? ? ? return cacheMap.computeIfAbsent(name, MyCache::new);

? ? }

? ? @Override

? ? public Collection<String> getCacheNames() {

? ? ? ? return cacheMap.keySet();

? ? }

? ? @Override

? ? public void afterPropertiesSet() throws Exception {

? ? ? ? System.out.println("say something!");

? ? }

}


CacheManager有兩個(gè)方法需要被實(shí)現(xiàn):

getCache(String)?- 獲取緩存存取器抛丽。這里的name其實(shí)就對(duì)應(yīng)了@Cacheable注解中的value與cacheName參數(shù)。

getCacheNames?- 獲取類中所有緩存的名稱集合柬帕。這主要是為了Spring內(nèi)部的統(tǒng)一管理需要陷寝。

因?yàn)?Spring采用了默認(rèn)替補(bǔ)策略,所以我們使用@Component或是通過(guò)@Bean自動(dòng)注入后爆安,默認(rèn)的緩存管理器就會(huì)切換成我們自定義的扔仓。如果我們自定義了兩個(gè)的話咖耘,可以通過(guò)@Primary來(lái)設(shè)定默認(rèn)管理器儿倒。

Cache

緩存存取器,用來(lái)管理緩存鍵值對(duì)的基本單元彻犁。

為了能對(duì)不同的緩存采用不同的存取策略汞幢,我們可以定制不同的Cache微谓,并通過(guò)自定義的CacheManager的getCache方法返回對(duì)應(yīng)的Cache。

舉個(gè)例子:

public final static class MyCache extends ConcurrentMapCache {

? ? public MyCache(String name) {

? ? ? ? super(name);

? ? }

? ? @Override

? ? public <T> T get(Object key, Class<T> type) {

? ? ? ? System.out.println("正在讀取 - " + key);

? ? ? ? return super.get(key, type);

? ? }

? ? @Override

? ? public <T> T get(Object key, Callable<T> valueLoader) {

? ? ? ? System.out.println("正在讀取 - " + key);

? ? ? ? return super.get(key, valueLoader);

? ? }

? ? @Override

? ? public ValueWrapper get(Object key) {

? ? ? ? System.out.println("正在讀取 - " + key);

? ? ? ? return super.get(key);

? ? }

}

這里的MyCache集成了ConcurrentMapCache疾宏,并對(duì)每次緩存值的獲取都進(jìn)行了控制臺(tái)輸出坎藐。

KeyGenerator

緩存key生成器哼绑,用于自定義規(guī)則緩存key的生成抖韩。

其接口的方法只有一個(gè):

public interface KeyGenerator {

? ? Object generate(Object target, Method method, Object... params);

}

一目了然,通過(guò)調(diào)用的目標(biāo)對(duì)象茂浮、目標(biāo)方法與方法入?yún)⑦M(jìn)行key的生成。這里不做過(guò)多贅述顽馋。

不過(guò)需要注意的是,由于不同類可能有同名同參數(shù)的方法竟稳,這里建議加上target.getClass().getName()來(lái)作為標(biāo)記熊痴,避免出現(xiàn)不希望的緩存映射果善。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末岭埠,一起剝皮案震驚了整個(gè)濱河市蔚鸥,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌馆类,老刑警劉巖弹谁,帶你破解...
    沈念sama閱讀 222,627評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件预愤,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡旷太,警方通過(guò)查閱死者的電腦和手機(jī)供璧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,180評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門冻记,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)冗栗,“玉大人供搀,你說(shuō)我怎么就攤上這事趁曼∽匮螅” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 169,346評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)愧捕。 經(jīng)常有香客問(wèn)我,道長(zhǎng)瘪阁,這世上最難降的妖魔是什么邮偎? 我笑而不...
    開(kāi)封第一講書人閱讀 60,097評(píng)論 1 300
  • 正文 為了忘掉前任禾进,我火速辦了婚禮,結(jié)果婚禮上泻云,老公的妹妹穿的比我還像新娘。我一直安慰自己卸夕,他們只是感情好婆瓜,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,100評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布勃救。 她就那樣靜靜地躺著,像睡著了一般蒙秒。 火紅的嫁衣襯著肌膚如雪晕讲。 梳的紋絲不亂的頭發(fā)上马澈,一...
    開(kāi)封第一講書人閱讀 52,696評(píng)論 1 312
  • 那天痊班,我揣著相機(jī)與錄音涤伐,去河邊找鬼。 笑死凝果,一個(gè)胖子當(dāng)著我的面吹牛器净,可吹牛的內(nèi)容都是我干的山害。 我是一名探鬼主播,決...
    沈念sama閱讀 41,165評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼欧瘪!你這毒婦竟也來(lái)了佛掖?” 一聲冷哼從身側(cè)響起涌庭,我...
    開(kāi)封第一講書人閱讀 40,108評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤坐榆,失蹤者是張志新(化名)和其女友劉穎席镀,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體顶捷,經(jīng)...
    沈念sama閱讀 46,646評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡服赎,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,709評(píng)論 3 342
  • 正文 我和宋清朗相戀三年重虑,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片永高。...
    茶點(diǎn)故事閱讀 40,861評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡乏梁,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出遇骑,到底是詐尸還是另有隱情揖曾,我是刑警寧澤,帶...
    沈念sama閱讀 36,527評(píng)論 5 351
  • 正文 年R本政府宣布练链,位于F島的核電站媒鼓,受9級(jí)特大地震影響绿鸣,放射性物質(zhì)發(fā)生泄漏潮模。R本人自食惡果不足惜痴施,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,196評(píng)論 3 336
  • 文/蒙蒙 一动遭、第九天 我趴在偏房一處隱蔽的房頂上張望神得。 院中可真熱鬧,春花似錦绵估、人聲如沸国裳。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,698評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)缝左。三九已至亿遂,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間渺杉,已是汗流浹背蛇数。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,804評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留是越,地道東北人耳舅。 一個(gè)月前我還...
    沈念sama閱讀 49,287評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像倚评,于是被迫代替她去往敵國(guó)和親浦徊。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,860評(píng)論 2 361

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