掃二維碼與項目經(jīng)理溝通
我們在微信上24小時期待你的聲音
解答本文疑問/技術(shù)咨詢/運營咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流
作者最近在開發(fā)公司項目時使用到 Redis 緩存,并在翻看前人代碼時,看到了一種關(guān)于 @Cacheable 注解的自定義緩存有效期的解決方案,感覺比較實用,因此作者自己拓展完善了一番后分享給各位。

創(chuàng)新互聯(lián)是一家集網(wǎng)站建設(shè),商洛企業(yè)網(wǎng)站建設(shè),商洛品牌網(wǎng)站建設(shè),網(wǎng)站定制,商洛網(wǎng)站建設(shè)報價,網(wǎng)絡(luò)營銷,網(wǎng)絡(luò)優(yōu)化,商洛網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強企業(yè)競爭力。可充分滿足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時我們時刻保持專業(yè)、時尚、前沿,時刻以成就客戶成長自我,堅持不斷學習、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實用型網(wǎng)站。
Spring Cache 框架給我們提供了 @Cacheable 注解用于緩存方法返回內(nèi)容。但是 @Cacheable 注解不能定義緩存有效期。這樣的話在一些需要自定義緩存有效期的場景就不太實用。
按照 Spring Cache 框架給我們提供的 RedisCacheManager 實現(xiàn),只能在全局設(shè)置緩存有效期。這里給大家看一個常規(guī)的 CacheConfig 緩存配置類,代碼如下,
@EnableCaching
@Configuration
public class CacheConfig extends CachingConfigurerSupport {
...
private RedisSerializer keySerializer() {
return new StringRedisSerializer();
}
private RedisSerializer 這里面簡單對 RedisCacheConfiguration 緩存配置做一下說明:
那么使用如上配置生成的 Redis 緩存 key 名稱是什么樣得嘞?這里用開源項目 crowd-admin 的 ConfigServiceImpl 類下 getValueByKey(String key) 方法舉例,
@Cacheable(value = "configCache", key = "#root.methodName + '_' + #root.args[0]")
@Override
public String getValueByKey(String key) {
QueryWrapper wrapper = new QueryWrapper<>();
wrapper.eq("configKey", key);
Config config = getOne(wrapper);
if (config == null) {
return null;
}
return config.getConfigValue();
} 執(zhí)行此方法后,Redis 中緩存 key 名稱如下,
crowd:configCache:getValueByKey_sys.name
圖片
TTL 過期時間是 287,跟我們?nèi)衷O(shè)置的 300 秒基本是一致的。此時假如我們想把 getValueByKey 方法的緩存有效期單獨設(shè)置為 600 秒,那我們該如何操作嘞?
@Cacheable 注解默認是沒有提供有關(guān)緩存有效期設(shè)置的。想要單獨修改 getValueByKey 方法的緩存有效期只能修改全局的緩存有效期。那么有沒有別的方法能夠為 getValueByKey 方法單獨設(shè)置緩存有效期嘞?當然是有的,大家請往下看。
其實我們可以通過自定義 MyRedisCacheManager 類繼承 Spring Cache 提供的 RedisCacheManager 類后,重寫 createRedisCache(String name, RedisCacheConfiguration cacheConfig) 方法,代碼如下,
public class MyRedisCacheManager extends RedisCacheManager {
public MyRedisCacheManager(RedisCacheWriter cacheWriter, RedisCacheConfiguration defaultCacheConfiguration) {
super(cacheWriter, defaultCacheConfiguration);
}
@Override
protected RedisCache createRedisCache(String name, RedisCacheConfiguration cacheConfig) {
String[] array = StringUtils.split(name, "#");
name = array[0];
// 解析 @Cacheable 注解的 value 屬性用以單獨設(shè)置有效期
if (array.length > 1) {
long ttl = Long.parseLong(array[1]);
cacheConfig = cacheConfig.entryTtl(Duration.ofSeconds(ttl));
}
return super.createRedisCache(name, cacheConfig);
}
}MyRedisCacheManager 類邏輯如下,
接著我們修改下 CacheConfig 類的 cacheManager 方法用以使用 MyRedisCacheManager 類。代碼如下,
@Bean
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
return new MyRedisCacheManager(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory), defaultCacheConfig());
}
private RedisCacheConfiguration defaultCacheConfig() {
return RedisCacheConfiguration.defaultCacheConfig()
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(keySerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(valueSerializer()))
.computePrefixWith(name -> CACHE_PREFIX + name + ":")
.entryTtl(Duration.ofSeconds(600));
}最后我們修改下 @Cacheable 注解使用方式,在原有 value 屬性的 configCache 值后添加 #600,單獨標識緩存有效期。代碼如下,
@Cacheable(value = "configCache#600", key = "#root.methodName + '_' + #root.args[0]")
@Override
public String getValueByKey(String key) {
...
}看下 getValueByKey 方法生成的 Redis 緩存 key 有效期是多久。如下,
圖片
OK,看到是 590 秒有效期后,我們就大功告成了,希望本文能對大家有所幫助。

我們在微信上24小時期待你的聲音
解答本文疑問/技術(shù)咨詢/運營咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流