Springboot中緩存推薦使用注解方式
參考:https://blog.csdn.net/wujiaqi0921/article/details/79123873
摘要
1.@Cacheable
@Cacheable可以標(biāo)記在一個(gè)方法上,也可以標(biāo)記在一個(gè)類(lèi)上找田。當(dāng)標(biāo)記在一個(gè)方法上時(shí)表示該方法是支持緩存的,當(dāng)標(biāo)記在一個(gè)類(lèi)上時(shí)則表示該類(lèi)所有的方法都是支持緩存的。
對(duì)于一個(gè)支持緩存的方法,Spring會(huì)在其被調(diào)用后將其返回值緩存起來(lái)剥汤,以保證下次利用同樣的參數(shù)來(lái)執(zhí)行該方法時(shí)可以直接從緩存中獲取結(jié)果失球,而不需要再次執(zhí)行該方法。
Spring在緩存方法的返回值時(shí)是以鍵值對(duì)進(jìn)行緩存的行您,值就是方法的返回結(jié)果,至于鍵的話(huà)剪廉,Spring又支持兩種策略娃循,默認(rèn)策略和自定義策略,需要注意的是當(dāng)一個(gè)支持緩存的方法在對(duì)象內(nèi)部被調(diào)用時(shí)是不會(huì)觸發(fā)緩存功能的斗蒋。
@Cacheable可以指定三個(gè)屬性捌斧,value笛质、key和condition。
- value:緩存的名稱(chēng)捞蚂,在 spring 配置文件中定義妇押,必須指定至少一個(gè)。如@Cacheable(value=”mycache”) 或者@Cacheable(value={”cache1”,”cache2”}
- key:緩存的 key姓迅,可以為空敲霍,如果指定要按照 SpEL 表達(dá)式編寫(xiě),如果不指定丁存,則缺省按照方法的所有參數(shù)進(jìn)行組合色冀。如@Cacheable(value=”testcache”,key=”#userName”)
- condition:緩存的條件,可以為空柱嫌,使用 SpEL 編寫(xiě)锋恬,返回 true 或者 false,只有為 true 才進(jìn)行緩存编丘。如@Cacheable(value=”testcache”,condition=”#userName.length()>2”)
注:除了上述使用方法參數(shù)作為key之外与学,Spring還為我們提供了一個(gè)root對(duì)象可以用來(lái)生成key。通過(guò)該root對(duì)象我們可以獲取到以下信息嘉抓。
- @Cacheable(cacheResolver=”MyCacheResolver”)執(zhí)行緩存解析器
- @Cacheable(cacheManager=”“)執(zhí)行緩存管理器索守,默認(rèn)使用currentMapCacheManager
- @Cacheable(cacheNames=”“)指定緩存的名稱(chēng)
- @Cacheable(keyGenerator=”“)在未指定key時(shí)指定緩存key值的生成器
- @Cacheable(unless=”“) 過(guò)濾不需要緩存的值,支持spEl表達(dá)式抑片。
public User findById(String id) {
System.out.println("執(zhí)行數(shù)據(jù)庫(kù)查詢(xún)方法");
return userDao.findById(id);
}
2.@CachePut
在支持Spring Cache的環(huán)境下卵佛,對(duì)于使用@Cacheable標(biāo)注的方法,Spring在每次執(zhí)行前都會(huì)檢查Cache中是否存在相同key的緩存元素敞斋,如果存在就不再執(zhí)行該方法截汪,而是直接從緩存中獲取結(jié)果進(jìn)行返回,否則才會(huì)執(zhí)行并將返回結(jié)果存入指定的緩存中植捎。
@CachePut也可以聲明一個(gè)方法支持緩存功能衙解。與@Cacheable不同的是使用@CachePut標(biāo)注的方法在執(zhí)行前不會(huì)去檢查緩存中是否存在之前執(zhí)行過(guò)的結(jié)果,而是每次都會(huì)執(zhí)行該方法焰枢,并將執(zhí)行結(jié)果以鍵值對(duì)的形式存入指定的緩存中蚓峦。
@CachePut也可以標(biāo)注在類(lèi)上和方法上。使用@CachePut時(shí)我們可以指定的屬性跟@Cacheable是一樣的济锄。
@CachePut(value = "user", key = "#id", condition = "#id != '321'")
public User findById(String id) {
System.out.println("執(zhí)行數(shù)據(jù)庫(kù)查詢(xún)方法");
return userDao.findById(id);
}
3.@CacheEvict
@CacheEvict是用來(lái)標(biāo)注在需要清除緩存元素的方法或類(lèi)上的暑椰。當(dāng)標(biāo)記在一個(gè)類(lèi)上時(shí)表示其中所有的方法的執(zhí)行都會(huì)觸發(fā)緩存的清除操作。
@CacheEvict可以指定的屬性有value荐绝、key一汽、condition、allEntries和beforeInvocation很泊。其中value角虫、key和condition的語(yǔ)義與@Cacheable對(duì)應(yīng)的屬性類(lèi)似沾谓。即value表示清除操作是發(fā)生在哪些Cache上的(對(duì)應(yīng)Cache的名稱(chēng))委造;key表示需要清除的是哪個(gè)key戳鹅,如未指定則會(huì)使用默認(rèn)策略生成的key;condition表示清除操作發(fā)生的條件昏兆。
下面我們來(lái)介紹一下新出現(xiàn)的兩個(gè)屬性allEntries和beforeInvocation枫虏。
- allEntries:是否清空所有緩存內(nèi)容,缺省為 false爬虱,如果指定為 true隶债,則方法調(diào)用后將立即清空所有緩存。如:@CachEvict(value=”testcache”,allEntries=true)
- beforeInvocation:是否在方法執(zhí)行前就清空跑筝,缺省為 false死讹,如果指定為 true,則在方法還沒(méi)有執(zhí)行的時(shí)候就清空緩存曲梗,缺省情況下赞警,如果方法執(zhí)行拋出異常,則不會(huì)清空緩存虏两。如:@CachEvict(value=”testcache”愧旦,beforeInvocation=true)
allEntries指定為true時(shí),則會(huì)清楚所有緩存定罢。
其他參數(shù)和@Cacheable相同
@CacheEvict(value = "user", key = "#id")
public void deleteUserById(String id) {
}
4.@Caching
@Caching注解可以讓我們?cè)谝粋€(gè)方法或者類(lèi)上同時(shí)指定多個(gè)Spring Cache相關(guān)的注解笤虫。其擁有三個(gè)屬性:cacheable、put和evict祖凫,分別用于指定@Cacheable琼蚯、@CachePut和@CacheEvict。使用如下
@Caching(cacheable = {@Cacheable(value = "user", key = "#id", condition = "#id != '123'"),
@Cacheable(value = "user", key = "#id", condition = "#id != '321'")}
)
public User findById(String id) {
System.out.println("執(zhí)行數(shù)據(jù)庫(kù)查詢(xún)方法");
return userDao.findById(id);
}
在上面我們沒(méi)有沒(méi)使用指定的緩存解析器惠况,以及key生成器凌停。那么我們?nèi)绾蝸?lái)實(shí)現(xiàn)自己的解析器,緩存管理類(lèi)或者key生成器呢售滤?我們可以通過(guò)實(shí)現(xiàn)org.springframework.cache.interceptor.KeyGenerator接口實(shí)現(xiàn)自己想要的主鍵生成器罚拟,通過(guò)org.springframework.cache.interceptor.CacheResolver接口來(lái)實(shí)現(xiàn)自己的緩存解析器。在這里就不進(jìn)行代碼展示了完箩。
這里還需要提到@CacheConfig用于指定類(lèi)全局配置赐俗。
另外,代碼行級(jí)使用弊知,我封裝了個(gè)工具類(lèi)
功能隨用隨增加阻逮,先提供基本的常用方法
package com.qdzklt.rdm.utils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.util.Collection;
/**
* 緩存操作工具類(lèi)
*/
@Component
public class CacheUtil {
private static RedisTemplate redisTemplate;
@Autowired
public void setRedisTemplate(RedisTemplate redisTemplate) {
CacheUtil.redisTemplate = redisTemplate;
}
/**
* 獲得RedisTemplate
*
* @return RedisTemplate
*/
public static RedisTemplate getRedisTemplate() {
return redisTemplate;
}
/**
* 是否包含某個(gè)key
*
* @param key key
* @return booble
*/
public static Boolean hasKey(Object key) {
return redisTemplate.hasKey(key);
}
/**
* 添加或更新
*
* @param key 鍵
* @param value 值
*/
public static void set(Object key, Object value) {
redisTemplate.opsForValue().set(key, value);
}
/**
* 獲取
*
* @param key 鍵
*/
public static Object get(Object key) {
return redisTemplate.opsForValue().get(key);
}
/**
* 刪除
*
* @param key 鍵
*/
public static void delete(Object key) {
redisTemplate.delete(key);
}
/**
* 刪除
*
* @param keys 鍵集合
*/
public static void delete(Collection keys) {
redisTemplate.delete(keys);
}
}