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

Spring Boot集成Caffeine缓存失效问题求助

Spring Boot+Caffeine缓存不生效问题排查

问题描述

第一次在Spring Boot中使用缓存,选择Caffeine做测试,但缓存未生效——每次请求都会从Catalog.getData()重新加载数据。调试确认CacheConfig已加载,通过println输出也能验证缓存没起作用。application.properties中无缓存相关配置,移除KeyGenerator后问题依旧,请问遗漏了什么配置?

相关代码

pom.xml

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
    <version>3.1.0</version>
</dependency>
<dependency>
    <groupId>com.github.ben-manes.caffeine</groupId>
    <artifactId>caffeine</artifactId>
    <version>3.1.6</version>
</dependency>

CacheConfig

import com.api.project.catalog.MyKeyGenerator;
import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.TimeUnit;

@Configuration
@EnableCaching
public class CacheConfig {

    @Bean
    public Caffeine<Object, Object> caffeineConfig() {
        return Caffeine.newBuilder()
                .expireAfterWrite(300, TimeUnit.SECONDS)
                .initialCapacity(10);
    }

    @Bean
    public CacheManager cacheManager(Caffeine<Object, Object> caffeine) {
        CaffeineCacheManager caffeineCacheManager = new CaffeineCacheManager();
        caffeineCacheManager.setCaffeine(caffeine);
        return caffeineCacheManager;
    }

    @Bean("myKeyGenerator")
    public KeyGenerator keyGenerator() {
        return new MyKeyGenerator();
    }
}

KeyGenerator

import org.springframework.cache.interceptor.KeyGenerator;
import java.lang.reflect.Method;

public class MyKeyGenerator implements KeyGenerator {
    public Object generate(Object target, Method method, Object... params) {
        return "my-concat-test-key";
    }
}

Catalog Service

import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

@Service
public class Catalog {
    @Cacheable(value = "mycache", keyGenerator = "myKeyGenerator")
    public String getData(Locale locale, String key) {
        System.out.println(locale.toString() + " " + key);
        return locale.toString() + " " + key;
    }
}

MyMessageSource

MessageSource已配置且可正常工作。

public class MyMessageSource implements MessageSource {
    @Override
    @Nullable
    public String getMessage(String code, @Nullable Object[] args, @Nullable String defaultMessage, Locale locale) {
        // Some logic
        return new Catalog().getData(locale, code);
    }

    @Override
    public String getMessage(String code, Object[] args, Locale locale) throws NoSuchMessageException {
        // Some logic
        return new Catalog().getData(locale, code);
    }

    @Override
    public String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException {
        // Some logic
        return new Catalog().getData(locale, code);
    }
}

问题根源与修复方案

核心问题

Spring的@Cacheable注解是基于AOP代理实现的,只有Spring容器管理的Bean才会被代理,缓存逻辑才会生效。你在MyMessageSource中直接通过new Catalog()创建对象,这个对象不受Spring容器管理,自然不会触发缓存拦截逻辑。

修复步骤

  1. 将MyMessageSource注册为Spring管理的Bean(添加@Component注解,或在配置类中手动注册)
  2. 通过依赖注入获取Catalog实例,而非手动new

修改后的MyMessageSource代码:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.NoSuchMessageException;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;

@Component
public class MyMessageSource implements MessageSource {

    private final Catalog catalog;

    // 推荐使用构造注入
    @Autowired
    public MyMessageSource(Catalog catalog) {
        this.catalog = catalog;
    }

    @Override
    @Nullable
    public String getMessage(String code, @Nullable Object[] args, @Nullable String defaultMessage, Locale locale) {
        // Some logic
        return catalog.getData(locale, code);
    }

    @Override
    public String getMessage(String code, Object[] args, Locale locale) throws NoSuchMessageException {
        // Some logic
        return catalog.getData(locale, code);
    }

    @Override
    public String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException {
        // Some logic
        String code = resolvable.getCodes()[0]; // 根据实际业务调整code获取逻辑
        return catalog.getData(locale, code);
    }
}

额外检查点

  • 确保所有Bean类(CacheConfig、Catalog、MyMessageSource)都在Spring Boot主启动类的扫描包范围内,或通过@ComponentScan指定扫描路径
  • Spring Boot 3.x要求JDK版本为17+,确认本地环境符合要求
  • 可添加日志配置查看缓存细节:
    logging.level.org.springframework.cache=DEBUG
    
    该配置会输出缓存的命中、创建、失效等日志,便于进一步排查。

内容的提问来源于stack exchange,提问作者Bademeister

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 13:44:56