作者最近在開(kāi)發(fā)公司項(xiàng)目時(shí)使用到 Redis 緩存,并在翻看前人代碼時(shí),看到了一種關(guān)于 @Cacheable 注解的自定義緩存有效期的解決方案,感覺(jué)比較實(shí)用,因此作者自己拓展完善了一番后分享給各位。
Spring 緩存常規(guī)配置
Spring Cache 框架給我們提供了 @Cacheable 注解用于緩存方法返回內(nèi)容。但是 @Cacheable 注解不能定義緩存有效期。這樣的話(huà)在一些需要自定義緩存有效期的場(chǎng)景就不太實(shí)用。
按照 Spring Cache 框架給我們提供的 RedisCacheManager 實(shí)現(xiàn),只能在全局設(shè)置緩存有效期。這里給大家看一個(gè)常規(guī)的 CacheConfig 緩存配置類(lèi),代碼如下,
@EnableCaching @Configuration publicclassCacheConfigextendsCachingConfigurerSupport{ ... privateRedisSerializerkeySerializer(){ returnnewStringRedisSerializer(); } privateRedisSerializer
這里面簡(jiǎn)單對(duì) RedisCacheConfiguration 緩存配置做一下說(shuō)明:
serializeKeysWith():設(shè)置 Redis 的 key 的序列化規(guī)則。
erializeValuesWith():設(shè)置 Redis 的 value 的序列化規(guī)則。
computePrefixWith():計(jì)算 Redis 的 key 前綴。
entryTtl():全局設(shè)置 @Cacheable 注解緩存的有效期。
那么使用如上配置生成的 Redis 緩存 key 名稱(chēng)是什么樣得嘞?這里用開(kāi)源項(xiàng)目 crowd-admin 的 ConfigServiceImpl 類(lèi)下 getValueByKey(String key) 方法舉例,
@Cacheable(value="configCache",key="#root.methodName+'_'+#root.args[0]") @Override publicStringgetValueByKey(Stringkey){ QueryWrapperwrapper=newQueryWrapper<>(); wrapper.eq("configKey",key); Configconfig=getOne(wrapper); if(config==null){ returnnull; } returnconfig.getConfigValue(); }
執(zhí)行此方法后,Redis 中緩存 key 名稱(chēng)如下,
crowdgetValueByKey_sys.name
TTL 過(guò)期時(shí)間是 287,跟我們?nèi)衷O(shè)置的 300 秒基本是一致的。此時(shí)假如我們想把 getValueByKey 方法的緩存有效期單獨(dú)設(shè)置為 600 秒,那我們?cè)撊绾尾僮鬣希?/p>
@Cacheable 注解默認(rèn)是沒(méi)有提供有關(guān)緩存有效期設(shè)置的。想要單獨(dú)修改 getValueByKey 方法的緩存有效期只能修改全局的緩存有效期。那么有沒(méi)有別的方法能夠?yàn)?getValueByKey 方法單獨(dú)設(shè)置緩存有效期嘞?當(dāng)然是有的,大家請(qǐng)往下看。
自定義 MyRedisCacheManager 緩存
其實(shí)我們可以通過(guò)自定義 MyRedisCacheManager 類(lèi)繼承 Spring Cache 提供的 RedisCacheManager 類(lèi)后,重寫(xiě) createRedisCache(String name, RedisCacheConfiguration cacheConfig) 方法,代碼如下,
publicclassMyRedisCacheManagerextendsRedisCacheManager{ publicMyRedisCacheManager(RedisCacheWritercacheWriter,RedisCacheConfigurationdefaultCacheConfiguration){ super(cacheWriter,defaultCacheConfiguration); } @Override protectedRedisCachecreateRedisCache(Stringname,RedisCacheConfigurationcacheConfig){ String[]array=StringUtils.split(name,"#"); name=array[0]; //解析@Cacheable注解的value屬性用以單獨(dú)設(shè)置有效期 if(array.length>1){ longttl=Long.parseLong(array[1]); cacheConfig=cacheConfig.entryTtl(Duration.ofSeconds(ttl)); } returnsuper.createRedisCache(name,cacheConfig); } }
MyRedisCacheManager 類(lèi)邏輯如下,
繼承 Spring Cache 提供的 RedisCacheManager 類(lèi)。
重寫(xiě) createRedisCache(String name, RedisCacheConfiguration cacheConfig) 方法。
解析 name 參數(shù),根據(jù) # 字符串進(jìn)行分割,獲取緩存 key 名稱(chēng)以及緩存有效期。
接著我們修改下 CacheConfig 類(lèi)的 cacheManager 方法用以使用 MyRedisCacheManager 類(lèi)。代碼如下,
@Bean publicCacheManagercacheManager(RedisConnectionFactoryredisConnectionFactory){ returnnewMyRedisCacheManager(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory),defaultCacheConfig()); } privateRedisCacheConfigurationdefaultCacheConfig(){ returnRedisCacheConfiguration.defaultCacheConfig() .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(keySerializer())) .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(valueSerializer())) .computePrefixWith(name->CACHE_PREFIX+name+":") .entryTtl(Duration.ofSeconds(600)); }
最后我們修改下 @Cacheable 注解使用方式,在原有 value 屬性的 configCache 值后添加 #600,單獨(dú)標(biāo)識(shí)緩存有效期。代碼如下,
@Cacheable(value="configCache#600",key="#root.methodName+'_'+#root.args[0]") @Override publicStringgetValueByKey(Stringkey){ ... }
看下 getValueByKey 方法生成的 Redis 緩存 key 有效期是多久。如下,
OK,看到是 590 秒有效期后,我們就大功告成了,希望本文能對(duì)大家有所幫助。
審核編輯:劉清
-
Cache
+關(guān)注
關(guān)注
0文章
129瀏覽量
28433 -
緩存器
+關(guān)注
關(guān)注
0文章
63瀏覽量
11692 -
Redis
+關(guān)注
關(guān)注
0文章
378瀏覽量
10943
原文標(biāo)題:Spring Cache 緩存注解這樣用,實(shí)在是太香了!
文章出處:【微信號(hào):芋道源碼,微信公眾號(hào):芋道源碼】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
CPU Cache是如何保證緩存一致性的?
![CPU <b class='flag-5'>Cache</b>是如何保證<b class='flag-5'>緩存</b>一致性的?](https://file1.elecfans.com/web2/M00/B4/40/wKgZomVteeqAG-k5AABzTiQGyG0753.jpg)
基于javaPoet的緩存key優(yōu)化實(shí)踐
![基于javaPoet的<b class='flag-5'>緩存</b>key優(yōu)化實(shí)踐](https://file1.elecfans.com/web2/M00/EB/95/wKgZomZevfiAZTUiAAAYyNC3ogI340.png)
阿里巴巴開(kāi)源的通用緩存訪問(wèn)框架JetCache介紹
L2 Cache配置方案那種更好?
高速緩存(cache)的工作原理是什么?高速緩存可分為哪幾類(lèi)
高速緩存Cache介紹
什么是緩存Cache
什么是Cache
高速緩存(Cache),高速緩存(Cache)原理是什么?
Spring應(yīng)用 1 springXML配置說(shuō)明
二級(jí)緩存的簡(jiǎn)單配置教程詳解 淺談二級(jí)緩存之功效
![二級(jí)<b class='flag-5'>緩存</b>的簡(jiǎn)單<b class='flag-5'>配置</b>教程詳解 淺談二級(jí)<b class='flag-5'>緩存</b>之功效](https://file.elecfans.com/web1/M00/5C/31/pIYBAFtyhS6AZMojAABUg4ib75I200.jpg)
Linux內(nèi)核Page Cache和Buffer Cache兩類(lèi)緩存的作用及關(guān)系如何
![Linux內(nèi)核Page <b class='flag-5'>Cache</b>和Buffer <b class='flag-5'>Cache</b>兩類(lèi)<b class='flag-5'>緩存</b>的作用及關(guān)系如何](https://file.elecfans.com/web2/M00/05/4A/pYYBAGDet7-AcS-1AACiXmSPUwY005.png)
評(píng)論