You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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内存缓存为例:

  1. 首先引入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>
  1. 配置带过期的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 14:21:02