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容器管理,自然不会触发缓存拦截逻辑。
修复步骤
- 将
MyMessageSource注册为Spring管理的Bean(添加@Component注解,或在配置类中手动注册) - 通过依赖注入获取
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
相关产品推荐
相关产品推荐

