Springboot中緩存推薦使用注解方式
參考:https://blog.csdn.net/wujiaqi0921/article/details/79123873
摘要
1.@Cacheable
@Cacheable可以標(biāo)記在一個(gè)方法上,也可以標(biāo)記在一個(gè)類上。當(dāng)標(biāo)記在一個(gè)方法上時(shí)表示該方法是支持緩存的,當(dāng)標(biāo)記在一個(gè)類上時(shí)則表示該類所有的方法都是支持緩存的。
對(duì)于一個(gè)支持緩存的方法,Spring會(huì)在其被調(diào)用后將其返回值緩存起來(lái),以保證下次利用同樣的參數(shù)來(lái)執(zhí)行該方法時(shí)可以直接從緩存中獲取結(jié)果,而不需要再次執(zhí)行該方法。
Spring在緩存方法的返回值時(shí)是以鍵值對(duì)進(jìn)行緩存的,值就是方法的返回結(jié)果,至于鍵的話,Spring又支持兩種策略,默認(rèn)策略和自定義策略,需要注意的是當(dāng)一個(gè)支持緩存的方法在對(duì)象內(nèi)部被調(diào)用時(shí)是不會(huì)觸發(fā)緩存功能的。
@Cacheable可以指定三個(gè)屬性,value、key和condition。
- value:緩存的名稱,在 spring 配置文件中定義,必須指定至少一個(gè)。如@Cacheable(value=”mycache”) 或者@Cacheable(value={”cache1”,”cache2”}
- key:緩存的 key,可以為空,如果指定要按照 SpEL 表達(dá)式編寫,如果不指定,則缺省按照方法的所有參數(shù)進(jìn)行組合。如@Cacheable(value=”testcache”,key=”#userName”)
- condition:緩存的條件,可以為空,使用 SpEL 編寫,返回 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=”“)指定緩存的名稱
- @Cacheable(keyGenerator=”“)在未指定key時(shí)指定緩存key值的生成器
- @Cacheable(unless=”“) 過(guò)濾不需要緩存的值,支持spEl表達(dá)式。

public User findById(String id) {
System.out.println("執(zhí)行數(shù)據(jù)庫(kù)查詢方法");
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)注在類上和方法上。使用@CachePut時(shí)我們可以指定的屬性跟@Cacheable是一樣的。
@CachePut(value = "user", key = "#id", condition = "#id != '321'")
public User findById(String id) {
System.out.println("執(zhí)行數(shù)據(jù)庫(kù)查詢方法");
return userDao.findById(id);
}
3.@CacheEvict
@CacheEvict是用來(lái)標(biāo)注在需要清除緩存元素的方法或類上的。當(dāng)標(biāo)記在一個(gè)類上時(shí)表示其中所有的方法的執(zhí)行都會(huì)觸發(fā)緩存的清除操作。
@CacheEvict可以指定的屬性有value、key、condition、allEntries和beforeInvocation。其中value、key和condition的語(yǔ)義與@Cacheable對(duì)應(yīng)的屬性類似。即value表示清除操作是發(fā)生在哪些Cache上的(對(duì)應(yīng)Cache的名稱);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è)方法或者類上同時(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ù)查詢方法");
return userDao.findById(id);
}
在上面我們沒(méi)有沒(méi)使用指定的緩存解析器,以及key生成器。那么我們?nèi)绾蝸?lái)實(shí)現(xiàn)自己的解析器,緩存管理類或者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用于指定類全局配置。
另外,代碼行級(jí)使用,我封裝了個(gè)工具類
功能隨用隨增加,先提供基本的常用方法
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;
/**
* 緩存操作工具類
*/
@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);
}
}