Spring @Cacheable注解中key的使用詳解
Spring @Cacheable注解中key使用
key屬性是用來指定Spring緩存方法的返回結(jié)果時對應(yīng)的key的。該屬性支持SpringEL表達式。當我們沒有指定該屬性時,Spring將使用默認策略生成key。我們這里先來看看自定義策略,至于默認策略會在后文單獨介紹。
自定義策略是指我們可以通過Spring的EL表達式來指定我們的key。這里的EL表達式可以使用方法參數(shù)及它們對應(yīng)的屬性。使用方法參數(shù)時我們可以直接使用“#參數(shù)名”或者“#p參數(shù)index”。
下面是幾個使用參數(shù)作為key的示例
@Cacheable(value="users", key="#id")
public User find(Integer id) {
returnnull;
}
@Cacheable(value="users", key="#p0")
public User find(Integer id) {
returnnull;
}
@Cacheable(value="users", key="#user.id")
public User find(User user) {
returnnull;
}
@Cacheable(value="users", key="#p0.id")
public User find(User user) {
returnnull;
}
除了上述使用方法參數(shù)作為key之外,Spring還為我們提供了一個root對象可以用來生成key。通過該root對象我們可以獲取到以下信息。

當我們要使用root對象的屬性作為key時我們也可以將“#root”省略,因為Spring默認使用的就是root對象的屬性。如:
@Cacheable(value={"users", "xxx"}, key="caches[1].name")
public User find(User user) {
returnnull;
}
如果要調(diào)用當前類里面的方法
當我們要使用root對象的屬性作為key時我們也可以將“#root”省略,因為Spring默認使用的就是root對象的屬性。如:
@Cacheable(value={"users", "xxx"}, key="caches[1].name")
public User find(User user) {
returnnull;
}
如果要調(diào)用當前類里面的方法
@Override
@Cacheable(value={"TeacherAnalysis_public_chart"}, key="#root.target.getDictTableName() + '_' + #root.target.getFieldName()")
public List<Map<String, Object>> getChartList(Map<String, Object> paramMap) {
}
public String getDictTableName(){
return "";
}
public String getFieldName(){
return "";
}
condition屬性指定發(fā)生的條件
有的時候我們可能并不希望緩存一個方法所有的返回結(jié)果。通過condition屬性可以實現(xiàn)這一功能。condition屬性默認為空,表示將緩存所有的調(diào)用情形。其值是通過SpringEL表達式來指定的,當為true時表示進行緩存處理;當為false時表示不進行緩存處理,即每次調(diào)用該方法時該方法都會執(zhí)行一次。如下示例表示只有當user的id為偶數(shù)時才會進行緩存
@Cacheable(value={"users"}, key="#user.id", condition="#user.id%2==0")
public User find(User user) {
System.out.println("find user by user " + user);
return user;
}
@CachePut
在支持Spring Cache的環(huán)境下,對于使用@Cacheable標注的方法,Spring在每次執(zhí)行前都會檢查Cache中是否存在相同key的緩存元素,如果存在就不再執(zhí)行該方法,而是直接從緩存中獲取結(jié)果進行返回,否則才會執(zhí)行并將返回結(jié)果存入指定的緩存中。@CachePut也可以聲明一個方法支持緩存功能。與@Cacheable不同的是使用@CachePut標注的方法在執(zhí)行前不會去檢查緩存中是否存在之前執(zhí)行過的結(jié)果,而是每次都會執(zhí)行該方法,并將執(zhí)行結(jié)果以鍵值對的形式存入指定的緩存中。
@CachePut也可以標注在類上和方法上。使用@CachePut時我們可以指定的屬性跟@Cacheable是一樣的。
@CachePut("users")//每次都會執(zhí)行方法,并將結(jié)果存入指定的緩存中
public User find(Integer id) {
return null;
}
@CacheEvict
@CacheEvict是用來標注在需要清除緩存元素的方法或類上的。當標記在一個類上時表示其中所有的方法的執(zhí)行都會觸發(fā)緩存的清除操作。@CacheEvict可以指定的屬性有value、key、condition、allEntries和beforeInvocation。其中value、key和condition的語義與@Cacheable對應(yīng)的屬性類似。即value表示清除操作是發(fā)生在哪些Cache上的(對應(yīng)Cache的名稱);key表示需要清除的是哪個key,如未指定則會使用默認策略生成的key;condition表示清除操作發(fā)生的條件。下面我們來介紹一下新出現(xiàn)的兩個屬性allEntries和beforeInvocation。
allEntries屬性
allEntries是boolean類型,表示是否需要清除緩存中的所有元素。默認為false,表示不需要。當指定了allEntries為true時,Spring Cache將忽略指定的key。有的時候我們需要Cache一下清除所有的元素,這比一個一個清除元素更有效率。
@CacheEvict(value="users", allEntries=true)
public void delete(Integer id) {
System.out.println("delete user by id: " + id);
}
beforeInvocation屬性
清除操作默認是在對應(yīng)方法成功執(zhí)行之后觸發(fā)的,即方法如果因為拋出異常而未能成功返回時也不會觸發(fā)清除操作。使用beforeInvocation可以改變觸發(fā)清除操作的時間,當我們指定該屬性值為true時,Spring會在調(diào)用該方法之前清除緩存中的指定元素。
@CacheEvict(value="users", beforeInvocation=true)
public void delete(Integer id) {
System.out.println("delete user by id: " + id);
}
其實除了使用@CacheEvict清除緩存元素外,當我們使用Ehcache作為實現(xiàn)時,我們也可以配置Ehcache自身的驅(qū)除策略,其是通過Ehcache的配置文件來指定的。由于Ehcache不是本文描述的重點,這里就不多贅述了,想了解更多關(guān)于Ehcache的信息,請查看我關(guān)于Ehcache的專欄。
@Caching
@Caching注解可以讓我們在一個方法或者類上同時指定多個Spring Cache相關(guān)的注解。其擁有三個屬性:cacheable、put和evict,分別用于指定@Cacheable、@CachePut和@CacheEvict。
@Caching(cacheable = @Cacheable("users"), evict = { @CacheEvict("cache2"),
@CacheEvict(value = "cache3", allEntries = true) })
public User find(Integer id) {
return null;
}
使用自定義注解
Spring允許我們在配置可緩存的方法時使用自定義的注解,前提是自定義的注解上必須使用對應(yīng)的注解進行標注。如我們有如下這么一個使用@Cacheable進行標注的自定義注解。
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Cacheable(value="users")
public @interface MyCacheable {
}
那么在我們需要緩存的方法上使用@MyCacheable進行標注也可以達到同樣的效果
@MyCacheable
public User findById(Integer id) {
System.out.println("find user by id: " + id);
User user = new User();
user.setId(id);
user.setName("Name" + id);
return user;
}
@Cacheable 拼接key
@Cacheable(value = "page_user",key ="T(String).valueOf(#page).concat('-').concat(#pageSize)",unless = "#result=null")//由于page是int型,concat要求變量必須為String,所以強轉(zhuǎn)一下
@Override
public List<SysUserEntity> page(int page, int pageSize) {
return userMapper.page(page,pageSize);
}
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
RabbitMQ 3.9.7 鏡像模式集群與Springboot 2.5.5 整合
今天我們來聊聊 RabbitMQ 3.9.7 鏡像模式集群與Springboot 2.5.5 整合,本文通過實例代碼給大家介紹的非常詳細,需要的朋友參考下吧2021-10-10
UniApp?+?SpringBoot?實現(xiàn)微信支付和退款功能
這篇文章主要介紹了UniApp?+?SpringBoot?實現(xiàn)微信支付和退款功能,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-06-06
淺談spring ioc的注入方式及注入不同的數(shù)據(jù)類型
這篇文章主要介紹了淺談spring ioc的注入方式及注入不同的數(shù)據(jù)類型,具有一定借鑒價值,需要的朋友可以參考下2017-12-12
Mybatis自動創(chuàng)建表和更新表結(jié)構(gòu)
這篇文章主要介紹了Mybatis自動創(chuàng)建表和更新表結(jié)構(gòu)的相關(guān)資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2016-06-06

