Spring Boot中如何为@Cacheable注解设置缓存过期时间?
Spring Boot
@Cacheable 配置过期时间方案 Spring 原生@Cacheable注解本身没有提供直接设置过期时间的参数,过期策略由底层绑定的CacheManager实现决定。你当前使用的ConcurrentMapCacheManager是Spring提供的轻量内存缓存实现,默认没有内置过期能力,以下是两种灵活的实现方案:
方案一:扩展ConcurrentMapCache实现过期(无需更换缓存类型)
你可以自定义带TTL(过期时间)的ConcurrentMapCache实现,重写缓存存取逻辑,通过访问时校验的方式清理过期缓存,示例代码如下:
public class TtlConcurrentMapCache extends ConcurrentMapCache { // 缓存过期时间,单位毫秒 private final long ttl; // 存储缓存写入时间 private final ConcurrentMap<Object, Long> writeTimeMap = new ConcurrentHashMap<>(); public TtlConcurrentMapCache(String name, long ttl) { super(name); this.ttl = ttl; } @Override public <T> T get(Object key, Callable<T> valueLoader) { // 先校验是否过期,过期则清除旧缓存 if (isExpired(key)) { evict(key); } T value = super.get(key, valueLoader); if (value != null) { writeTimeMap.put(key, System.currentTimeMillis()); } return value; } @Override public void put(Object key, Object value) { super.put(key, value); writeTimeMap.put(key, System.currentTimeMillis()); } private boolean isExpired(Object key) { Long writeTime = writeTimeMap.get(key); return writeTime != null && System.currentTimeMillis() - writeTime > ttl; } }
然后自定义CacheManager使用这个实现,支持为不同缓存单独设置过期时间:
@Configuration @EnableCaching public class CachingConfig { @Bean public CacheManager cacheManager() { ConcurrentMapCacheManager cacheManager = new ConcurrentMapCacheManager() { @Override protected Cache createConcurrentMapCache(String name) { // 给users缓存设置10分钟过期 if ("users".equals(name)) { return new TtlConcurrentMapCache(name, 10 * 60 * 1000); } // 其他缓存默认30分钟过期 return new TtlConcurrentMapCache(name, 30 * 60 * 1000); } }; cacheManager.setCacheNames(List.of("users")); return cacheManager; } }
该方案无需引入额外依赖,适合简单单体应用的内存缓存场景。
方案二:使用支持原生过期的缓存实现(更稳定灵活,生产环境推荐)
如果对缓存功能要求更高,推荐替换为Caffeine(内存缓存)或Redis(分布式缓存)这类自带过期策略的缓存实现,以Caffeine内存缓存为例:
- 首先引入Caffeine依赖:
<!-- Maven 依赖 --> <dependency> <groupId>com.github.benmanes.caffeine</groupId> <artifactId>caffeine</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency>
- 配置带过期的CaffeineCacheManager,无需修改原有业务的
@Cacheable注解:
@Configuration @EnableCaching public class CachingConfig { @Bean public CacheManager cacheManager() { // 全局默认过期配置:写入后10分钟过期 Caffeine<Object, Object> defaultCaffeine = Caffeine.newBuilder() .expireAfterWrite(10, TimeUnit.MINUTES); // 单独给users缓存配置过期:写入后5分钟过期 Map<String, Caffeine<Object, Object>> cacheConfigs = new HashMap<>(); cacheConfigs.put("users", Caffeine.newBuilder().expireAfterWrite(5, TimeUnit.MINUTES)); return CaffeineCacheManager.builder() .defaultCaffeine(defaultCaffeine) .customCacheConfigs(cacheConfigs) .build(); } }
该方案还支持更多缓存特性比如最大容量限制、软/弱引用回收、命中率统计等,适配不同业务场景。如果是分布式场景,只需替换为RedisCacheManager,同样可以为不同缓存名称设置独立的过期时间。
内容的提问来源于stack exchange,提问作者user16409822
相关产品推荐
相关产品推荐

