很久之前收藏的一篇文章,後來找不到出處了
一:Spring緩存抽象
Spring從3.1開始定義了org.springframework.cache.Cache和org.springframework.cache.CacheManager接口來統一不同的緩存技術;並支持使用JCache(JSR-107)註解簡化我們開發;
- Cache接口爲緩存的組件規範定義,包含緩存的各種操作集合;
- Cache接口下Spring提供了各種xxxCache的實現;如RedisCache,EhCacheCache ,ConcurrentMapCache等;
- 每次調用需要緩存功能的方法時,Spring會檢查檢查指定參數的指定的目標方法是否已經被調用過;如果有就直接從緩存中獲取方法調用後的結果,如果沒有就調用方法並緩存結果後返回給用戶。下次調用直接從緩存中獲取。
- 使用Spring緩存抽象時我們需要關注以下兩點:
- 確定方法需要被緩存以及他們的緩存策略
- 從緩存中讀取之前緩存存儲的數據
二:幾個重要概念&緩存註解
名稱 | 解釋 |
---|---|
Cache | 緩存接口,定義緩存操作。實現有:RedisCache、EhCacheCache、ConcurrentMapCache等 |
CacheManager | 緩存管理器,管理各種緩存(cache)組件 |
@Cacheable | 主要針對方法配置,能夠根據方法的請求參數對其進行緩存 |
@CacheEvict | 清空緩存 |
@CachePut | 保證方法被調用,又希望結果被緩存。與@Cacheable區別在於是否每次都調用方法,常用於更新 |
@EnableCaching | 開啓基於註解的緩存 |
keyGenerator | 緩存數據時key生成策略 |
serialize | 緩存數據時value序列化策略 |
@CacheConfig | 統一配置本類的緩存註解的屬性 |
@Cacheable/@CachePut/@CacheEvict 主要的參數
名稱 | 解釋 |
---|---|
value | 緩存的名稱,在 spring 配置文件中定義,必須指定至少一個 例如: @Cacheable(value=”mycache”) 或者@Cacheable(value={”cache1”,”cache2”} |
key | 緩存的 key,可以爲空,如果指定要按照 SpEL 表達式編寫, 如果不指定,則缺省按照方法的所有參數進行組合 例如: @Cacheable(value=”testcache”,key=”#id”) |
condition | 緩存的條件,可以爲空,使用 SpEL 編寫,返回 true 或者 false, 只有爲 true 才進行緩存/清除緩存 例如:@Cacheable(value=”testcache”,condition=”#userName.length()>2”) |
unless | 否定緩存。當條件結果爲TRUE時,就不會緩存。 @Cacheable(value=”testcache”,unless=”#userName.length()>2”) |
allEntries (@CacheEvict ) |
是否清空所有緩存內容,缺省爲 false,如果指定爲 true, 則方法調用後將立即清空所有緩存 例如: @CachEvict(value=”testcache”,allEntries=true) |
beforeInvocation (@CacheEvict) |
是否在方法執行前就清空,缺省爲 false,如果指定爲 true, 則在方法還沒有執行的時候就清空緩存,缺省情況下,如果方法 執行拋出異常,則不會清空緩存 例如:@CachEvict(value=”testcache”,beforeInvocation=true) |
三:SpEL上下文數據
Spring Cache提供了一些供我們使用的SpEL上下文數據,下表直接摘自Spring官方文檔:
名稱 | 位置 | 描述 | 示例 |
---|---|---|---|
methodName | root對象 | 當前被調用的方法名 | #root.methodname |
method | root對象 | 當前被調用的方法 | #root.method.name |
target | root對象 | 當前被調用的目標對象實例 | #root.target |
targetClass | root對象 | 當前被調用的目標對象的類 | #root.targetClass |
args | root對象 | 當前被調用的方法的參數列表 | #root.args[0] |
caches | root對象 | 當前方法調用使用的緩存列表 | #root.caches[0].name |
Argument Name | 執行上下文 | 當前被調用的方法的參數, 如findArtisan(Artisan artisan),可以通過#artsian.id獲得參數 |
#artsian.id |
result | 執行上下文 | 方法執行後的返回值(僅當方法執行後的判斷有效, 如 unless cacheEvict的beforeInvocation=false) |
#result |
注意:
1.當我們要使用root對象的屬性作爲key時我們也可以將“#root”省略,因爲Spring默認使用的就是root對象的屬性。 如
@Cacheable(key = "targetClass + methodName +#p0")
2.使用方法參數時我們可以直接使用“#參數名”或者“#p參數index”。 如:
@Cacheable(value="users", key="#id")
@Cacheable(value="users", key="#p0")
SpEL提供了多種運算符
類型 | 運算符 |
---|---|
關係 | <,>,<=,>=,==,!=,lt,gt,le,ge,eq,ne |
算術 | +,- ,* ,/,%,^ |
邏輯 | &&, |
條件 | ?: (ternary),?: (elvis) |
正則表達式 | matches |
其他類型 | ?.,?[…],![…],1,$[…] |
以上的知識點適合你遺忘的時候來查閱,下面正式進入學習!
四:開始使用
環境:Spring boot 2.0.3
IDE:IDEA
1.開始使用前需要導入依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
2.然後在啓動類註解@EnableCaching開啓緩存
@SpringBootApplication
@EnableCaching//開啓緩存
public class DemoApplication{
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
3.緩存@Cacheable
@Cacheable
註解會先查詢是否已經有緩存,有會使用緩存,沒有則會執行方法並緩存。
@Cacheable(value = "emp" ,key = "targetClass + methodName +#p0")
public List<NewJob> queryAll(User uid) {
return newJobDao.findAllByUid(uid);
}
此處的value
是必需的,它指定了你的緩存存放在哪塊命名空間。
此處的key
是使用的spEL表達式,參考上章。這裏有一個小坑,如果你把methodName
換成method
運行會報錯,觀察它們的返回類型,原因在於methodName
是String
而methoh
是Method
。
此處的User
實體類一定要實現序列化public class User implements Serializable
,否則會報java.io.NotSerializableException
異常。
到這裏,你已經可以運行程序檢驗緩存功能是否實現。
深入源碼,查看它的其它屬性
我們打開@Cacheable
註解的源碼,可以看到該註解提供的其他屬性,如:
String[] cacheNames() default {}; //和value註解差不多,二選一
String keyGenerator() default ""; //key的生成器。key/keyGenerator二選一使用
String cacheManager() default ""; //指定緩存管理器
String cacheResolver() default ""; //或者指定獲取解析器
String condition() default ""; //條件符合則緩存
String unless() default ""; //條件符合則不緩存
boolean sync() default false; //是否使用異步模式
4.配置@CacheConfig
當我們需要緩存的地方越來越多,你可以使用@CacheConfig(cacheNames = {"myCache"})
註解來統一指定value
的值,這時可省略value
,如果你在你的方法依舊寫上了value
,那麼依然以方法的value
值爲準。
使用方法如下:
@CacheConfig(cacheNames = {"myCache"})
public class BotRelationServiceImpl implements BotRelationService {
@Override
@Cacheable(key = "targetClass + methodName +#p0")//此處沒寫value
public List<BotRelation> findAllLimit(int num) {
return botRelationRepository.findAllLimit(num);
}
.....
}
查看它的其它屬性
String keyGenerator() default "";//key的生成器。key/keyGenerator二選一使用
String cacheManager() default "";//指定緩存管理器
String cacheResolver() default ""; //或者指定獲取解析器
5.更新@CachePut
@CachePut
註解的作用 主要針對方法配置,能夠根據方法的請求參數對其結果進行緩存,和 @Cacheable
不同的是,它每次都會觸發真實方法的調用 。簡單來說就是用戶更新緩存數據。但需要注意的是該註解的value
和 key
必須與要更新的緩存相同,也就是與@Cacheable
相同。示例:
@CachePut(value = "emp", key = "targetClass + #p0")
public NewJob updata(NewJob job) {
NewJob newJob = newJobDao.findAllById(job.getId());
newJob.updata(job);
return job;
}
@Cacheable(value = "emp", key = "targetClass +#p0")//清空緩存
public NewJob save(NewJob job) {
newJobDao.save(job);
return job;
}
查看它的其它屬性
String[] cacheNames() default {}; //與value二選一
String keyGenerator() default "";//key的生成器。key/keyGenerator二選一使用
String cacheManager() default "";//指定緩存管理器
String cacheResolver() default ""; //或者指定獲取解析器
String condition() default ""; //條件符合則緩存
String unless() default ""; //條件符合則不緩存
6.清除@CacheEvict
@CachEvict
的作用 主要針對方法配置,能夠根據一定的條件對緩存進行清空 。
屬性 | 解釋 | 示例 |
---|---|---|
allEntries | 是否清空所有緩存內容,缺省爲 false,如果指定爲 true,則方法調用後將立即清空所有緩存 | @CachEvict(value=”testcache”,allEntries=true) |
beforeInvocation | 是否在方法執行前就清空,缺省爲 false,如果指定爲 true,則在方法還沒有執行的時候就清空緩存,缺省情況下,如果方法執行拋出異常,則不會清空緩存 | @CachEvict(value=”testcache”,beforeInvocation=true) |
示例:
@Cacheable(value = "emp",key = "#p0.id")
public NewJob save(NewJob job) {
newJobDao.save(job);
return job;
}
//清除一條緩存,key爲要清空的數據
@CacheEvict(value="emp",key="#id")
public void delect(int id) {
newJobDao.deleteAllById(id);
}
//方法調用後清空所有緩存
@CacheEvict(value="accountCache",allEntries=true)
public void delectAll() {
newJobDao.deleteAll();
}
//方法調用前清空所有緩存
@CacheEvict(value="accountCache",beforeInvocation=true)
public void delectAll() {
newJobDao.deleteAll();
}
其他屬性
String[] cacheNames() default {}; //與value二選一
String keyGenerator() default "";//key的生成器。key/keyGenerator二選一使用
String cacheManager() default "";//指定緩存管理器
String cacheResolver() default ""; //或者指定獲取解析器
String condition() default ""; //條件符合則清空
7.組合@Caching
有時候我們可能組合多個Cache註解使用,此時就需要@Caching組合多個註解標籤了。
@Caching(cacheable = {
@Cacheable(value = "emp",key = "#p0"),
...
},
put = {
@CachePut(value = "emp",key = "#p0"),
...
},evict = {
@CacheEvict(value = "emp",key = "#p0"),
....
})
public User save(User user) {
....
}
… ↩︎