Spring Boot 3中如何获取指定的CacheManager
解决方案
问题1:获取已存在的目标CacheManager
方法1:通过Spring上下文筛选所有CacheManager实例
Spring会将应用中所有的CacheManager注册为Bean,你可以注入List<CacheManager>后筛选出目标实例:
import org.springframework.cache.CacheManager; import org.springframework.cache.jcache.JCacheCacheManager; import org.springframework.beans.factory.annotation.Autowired; import javax.cache.CacheManager as JCacheManager; // 在需要的类中注入 @Autowired private List<CacheManager> cacheManagers; public CacheManager getTargetEhcacheManager() { for (CacheManager cm : cacheManagers) { // 针对Ehcache(实现JSR107),获取底层JCache原生管理器 if (cm instanceof JCacheCacheManager jCacheWrapper) { JCacheManager underlyingManager = jCacheWrapper.getCacheManager(); // 匹配自定义配置的URI if ("classpath:ehcache.xml".equals(underlyingManager.getURI().toString())) { return cm; } } // 若自定义CacheManager时指定了Bean名称,也可直接通过名称判断 // if ("customEhcacheManager".equals(((org.springframework.beans.factory.BeanNameAware)cm).getBeanName())) { // return cm; // } } throw new IllegalStateException("未找到目标CacheManager"); }
方法2:自定义CacheManager时指定Bean名称,通过@Qualifier直接注入
在配置类中显式定义自定义CacheManager并指定Bean名称,后续通过@Qualifier精准注入:
import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.jcache.JCacheCacheManager; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.cache.Caching; import javax.cache.CacheManager as JCacheManager; import java.net.URI; @Configuration @EnableCaching public class CustomCacheConfig { @Bean(name = "customEhcacheManager") public CacheManager customEhcacheManager() throws Exception { URI configUri = new URI("classpath:ehcache.xml"); JCacheManager jCacheManager = Caching.getCachingProvider() .getCacheManager(configUri, this.getClass().getClassLoader()); return new JCacheCacheManager(jCacheManager); } }
在需要使用的类中直接注入:
import org.springframework.cache.CacheManager; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; @Autowired @Qualifier("customEhcacheManager") private CacheManager targetCacheManager;
方法3:通过JCache原生API筛选已注册管理器
直接通过JSR107的CachingProvider获取所有已注册的原生CacheManager,筛选目标实例:
import javax.cache.Caching; import javax.cache.CacheManager as JCacheManager; import org.springframework.cache.jcache.JCacheCacheManager; import org.springframework.cache.CacheManager; public CacheManager getExistingEhcacheManager() { for (JCacheManager cm : Caching.getCachingProvider().getCacheManagers()) { if ("classpath:ehcache.xml".equals(cm.getURI().toString())) { return new JCacheCacheManager(cm); } } throw new IllegalStateException("未找到目标CacheManager"); }
问题2:提供正确的类加载器
你遇到重复创建管理器的核心原因是:重复调用getCacheManager(uri, classLoader)时,若类加载器不匹配,会被视为不同的管理器实例。在Spring Boot环境中,正确的类加载器获取方式有两种:
使用Spring应用上下文的类加载器:
import org.springframework.context.ApplicationContext; @Autowired private ApplicationContext applicationContext; // 获取正确的类加载器 ClassLoader correctClassLoader = applicationContext.getClassLoader();使用当前线程的上下文类加载器:
Spring Boot启动后,线程上下文类加载器默认就是应用的类加载器:ClassLoader correctClassLoader = Thread.currentThread().getContextClassLoader();
使用上述类加载器调用getCacheManager时,会复用已存在的管理器实例,避免重复创建缓存。
内容的提问来源于stack exchange,提问作者Slevin
相关产品推荐
相关产品推荐

