今天我被要求为我们的应用程序使用的一些键设置缓存的过期时间,所以我很快开始寻找 Spring @Cacheable 符号提供的所有选项来设置过期时间或生活的时间。由于 Spring 不提供任何可配置的选项来实现它,我构建了一个利用 @Scheduled 具有固定延迟的注释的实现,如下所示:
@CacheEvict(allEntries = true, cacheNames = { "EMPLOYEE_", "MANAGER_" }) @Scheduled(fixedDelay = 30000) public void cacheEvict() { }
现在的问题是我希望缓存名称以及固定延迟时间段应该从环境值而不是硬编码值中填充。为了达到同样的目的,我在类级别声明了变量(从属性文件填充)并填充了注释中的键值,这使得 IDE 抱怨值必须是常量,如下所示:
“注释属性 CacheEvict.cacheNames 的值必须是常量表达式”
然后我开始寻找其他选项来从环境中获取键的值,并遇到了 @Scheduled 符号的 fixedDelayString 元素,这帮助我实现了我的目标,如下所示:
@Scheduled(fixedDelayString = "${couchbase.cache.flush.fixed.delay}") public void cacheEvict() { }
也在为 @CacheEvict 注释寻找类似的元素,不幸的是,在阅读了关于错误 SPR-10778 的评论后给我提示,它说:
“缓存抽象现在支持 CacheResolver 抽象,它可以在全局、每个类和/或特定操作上指定。 CacheResolver 使您能够计算要在代码中使用的缓存,因此您拥有所需的所有灵活性。”
由于 bug 说要使用 CacheResolver 来动态填充缓存名称,我使用 AbstractCacheResolver 实现它来从环境中获取缓存名称,如下所示:
@Value("#{'${couchbase.cache.flush}'}") private String couchbaseCacheFlush; @Bean(name = "customCacheResolver") public CacheResolver cacheResolver() { CacheResolver cacheResolver = new AbstractCacheResolver(cacheManager()) { @Override protected Collection<String> getCacheNames( CacheOperationInvocationContext<?> context) { return Arrays.asList(couchbaseCacheFlush.split(",")); } }; return cacheResolver; }
修改 cacheEvict() 以使用自定义缓存解析器而不是缓存名称完成我当天的任务,如下所示:
@CacheEvict(allEntries = true, cacheResolver = "customCacheResolver") @Scheduled(fixedDelayString = "${couchbase.cache.flush.fixed.delay}") public void cacheEvict() { }
github 上提供了完整的源代码。
标签2: Java教程地址:https://www.cundage.com/article/jcg-setting-ttl-cacheable-spring.html