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

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环境中,正确的类加载器获取方式有两种:

  1. 使用Spring应用上下文的类加载器:

    import org.springframework.context.ApplicationContext;
    @Autowired
    private ApplicationContext applicationContext;
    
    // 获取正确的类加载器
    ClassLoader correctClassLoader = applicationContext.getClassLoader();
    
  2. 使用当前线程的上下文类加载器:
    Spring Boot启动后,线程上下文类加载器默认就是应用的类加载器:

    ClassLoader correctClassLoader = Thread.currentThread().getContextClassLoader();
    

使用上述类加载器调用getCacheManager时,会复用已存在的管理器实例,避免重复创建缓存。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 20:12:39