多依赖共用Caffeine缓存时缓存找不到异常的解决方法
解决方案:Spring多依赖缓存冲突处理
问题根源
你的应用中,依赖A的缓存配置仅初始化了名为user的缓存,而依赖B的@Cacheable注解引用了未被初始化的security.remotePublicKeyCache缓存名;同时若容器中存在多个CacheManager Bean且未指定默认实例,Spring无法自动匹配到正确的缓存管理器,导致抛出找不到缓存的异常。
可行方案
方案1:扩展默认缓存管理器,支持动态创建缓存
修改依赖A的缓存配置,将其标记为默认缓存管理器,并允许动态创建任意缓存名(默认开启,可显式声明),这样所有未指定缓存管理器的@Cacheable都会复用该实例,并自动创建所需缓存:
@Configuration @EnableCaching public class CaffeineConfiguration { @Primary // 标记为默认缓存管理器 @Bean(name="myCacheManager") public CacheManager cacheManager() { // 不指定初始缓存名,或同时包含A和B的缓存名 CaffeineCacheManager cacheManager = new CaffeineCacheManager(); cacheManager.setDynamic(true); // 显式开启动态创建(默认值为true,可省略) cacheManager.setCaffeine(caffeineConfig()); return cacheManager; } @Bean(name = "myCaffeineConfig") public Caffeine caffeineConfig() { return Caffeine.newBuilder() .expireAfterAccess(5, TimeUnit.MINUTES); } }
方案2:配置多缓存管理器,通过CacheResolver路由
若依赖A和B需要不同的缓存配置(如过期时间),可创建两个独立的CacheManager,并自定义CacheResolver根据缓存名自动匹配对应的管理器:
@Configuration @EnableCaching public class MultiCacheConfiguration implements CachingConfigurer { // 依赖A专属缓存管理器 @Bean(name="myCacheManager") public CacheManager userCacheManager() { CaffeineCacheManager cacheManager = new CaffeineCacheManager("user"); cacheManager.setCaffeine(userCaffeineConfig()); return cacheManager; } // 依赖B专属缓存管理器 @Bean(name="dependencyBCacheManager") public CacheManager dependencyBCacheManager() { CaffeineCacheManager cacheManager = new CaffeineCacheManager("security.remotePublicKeyCache"); cacheManager.setCaffeine(dependencyBCaffeineConfig()); return cacheManager; } @Bean(name = "myCaffeineConfig") public Caffeine userCaffeineConfig() { return Caffeine.newBuilder() .expireAfterAccess(5, TimeUnit.MINUTES); } @Bean(name = "dependencyBCaffeineConfig") public Caffeine dependencyBCaffeineConfig() { // 可根据依赖B的需求自定义缓存配置 return Caffeine.newBuilder() .expireAfterAccess(30, TimeUnit.MINUTES); } // 自定义缓存解析器,按缓存名路由 @Override public CacheResolver cacheResolver() { return new SimpleCacheResolver() { @Override protected Collection<? extends Cache> resolveCaches(CacheOperationInvocationContext<?> context) { String cacheName = context.getOperation().getCacheNames().iterator().next(); ApplicationContext ctx = getApplicationContext(); if ("security.remotePublicKeyCache".equals(cacheName)) { return Collections.singleton(ctx.getBean("dependencyBCacheManager", CacheManager.class).getCache(cacheName)); } return Collections.singleton(ctx.getBean("myCacheManager", CacheManager.class).getCache(cacheName)); } }; } }
方案3:提前初始化所有依赖的缓存名
若无需区分缓存配置,可直接在缓存管理器中初始化所有需要的缓存名(包括依赖B的),启动时一次性创建所有缓存:
@Configuration @EnableCaching public class CaffeineConfiguration { @Primary @Bean(name="myCacheManager") public CacheManager cacheManager() { // 同时初始化依赖A和B的缓存名 CaffeineCacheManager cacheManager = new CaffeineCacheManager("user", "security.remotePublicKeyCache"); cacheManager.setCaffeine(caffeineConfig()); return cacheManager; } @Bean(name = "myCaffeineConfig") public Caffeine caffeineConfig() { return Caffeine.newBuilder() .expireAfterAccess(5, TimeUnit.MINUTES); } }
内容的提问来源于stack exchange,提问作者Marcos
相关产品推荐
相关产品推荐

