如何在每日凌晨12点刷新Spring @Cacheable缓存?
实现每日凌晨12点刷新Ehcache缓存的方案
你提到的timeToIdleSeconds和timeToLiveSeconds确实是相对时间(从缓存条目创建/访问开始计算),没法直接实现“每天固定凌晨12点过期”的绝对时间需求。针对你的场景(用@Cacheable注解),我给你两种可行的实现思路:
方法一:结合Spring定时任务主动清除缓存(推荐,适配Ehcache 2.x/3.x)
这种方式最直接,通过定时任务在每天凌晨12点主动清除指定缓存,下次调用retrieveConfigurations()时会自动重新加载数据。
步骤1:开启Spring调度支持
在你的Spring配置类上添加@EnableScheduling注解,开启定时任务功能:
@Configuration @EnableScheduling public class CacheConfig { // 其他缓存配置... }
步骤2:编写定时清除缓存的方法
注入Spring的CacheManager,然后用@Scheduled注解指定凌晨12点的 cron 表达式:
@Component public class CacheRefreshTask { @Autowired private CacheManager cacheManager; // cron表达式:0秒 0分 0时 每天 每月 任意星期 @Scheduled(cron = "0 0 0 * * ?") public void clearCacheAtMidnight() { Cache cache = cacheManager.getCache("cacheName"); if (cache != null) { // 清除该缓存下的所有条目 cache.clear(); // 如果需要直接操作Ehcache原生对象(比如Ehcache 2.x的net.sf.ehcache.Cache) // ((net.sf.ehcache.Cache) cache.getNativeCache()).removeAll(); } } }
方法二:自定义Expiry实现绝对时间过期(仅Ehcache 3.x适用)
如果你用的是Ehcache 3.x(包路径为org.ehcache),可以通过实现Expiry接口,让每个缓存条目自动计算到次日凌晨12点的剩余过期时间。
自定义Expiry类
public class MidnightExpiry implements Expiry<Object, Object> { @Override public Duration getExpiryForCreation(Object key, Object value) { // 计算当前时间到次日凌晨12点的时间差 LocalDateTime now = LocalDateTime.now(); LocalDateTime nextMidnight = now.plusDays(1) .withHour(0) .withMinute(0) .withSecond(0) .withNano(0); return Duration.between(now, nextMidnight); } @Override public Duration getExpiryForAccess(Object key, ValueSupplier<?> value) { // 访问缓存时不延长过期时间,保持到凌晨过期 return null; } @Override public Duration getExpiryForUpdate(Object key, ValueSupplier<?> oldValue, Object newValue) { // 更新缓存时重新计算到凌晨的过期时间 return getExpiryForCreation(key, newValue); } }
配置缓存时使用该Expiry
在构建CacheConfiguration时指定自定义的过期策略:
@Bean public CacheManager cacheManager() { CacheConfiguration<Object, Object> cacheConfig = CacheConfigurationBuilder .newCacheConfigurationBuilder(Object.class, Object.class, ResourcePoolsBuilder.heap(100)) .withExpiry(new MidnightExpiry()) .build(); return EhcacheManagerBuilder.newCacheManagerBuilder() .withCache("cacheName", cacheConfig) .build(true); }
两种方案的区别
- 定时清除:不管缓存条目什么时候创建,每天凌晨12点统一清除,适合需要强制刷新数据的场景。
- 自定义Expiry:每个条目创建后,会自动到次日凌晨过期,如果是当天下午创建的缓存,会保留到第二天凌晨,适合允许缓存保留到当天结束的场景。
内容的提问来源于stack exchange,提问作者karfai
相关产品推荐
相关产品推荐

