springboot下 shiro使用ehcache和@cacheable冲突的处理

springboot提供缓存注解标签spring

@Cacheable ,当使用ehcache时,autoconfig机制会根据配置文件自动去初始化beanapache

而shiroConfig在@Configuration构造时,也会去初始化ehcache ,项目启动会产生以下异常缓存

org.apache.shiro.cache.CacheException: net.sf.ehcache.CacheException: Another unnamed CacheManager already exists in the same VM. Please provide unique names for each CacheManager in the config or do one of following:
1. Use one of the CacheManager.create() static factory methods to reuse same CacheManager with same name or create one if necessary
2. Shutdown the earlier cacheManager before creating new one with same name.

按照网上的说,使用低版本的ehcache可解决该问题,没找到完美解决的方法springboot

查看了下源代码ide

EhCacheCacheConfiguration在ui

@Bean
@ConditionalOnMissingBean
public net.sf.ehcache.CacheManager ehCacheCacheManager() {
    Resource location = this.cacheProperties.resolveConfigLocation(this.cacheProperties.getEhcache().getConfig());
    return location != null ? EhCacheManagerUtils.buildCacheManager(location) : EhCacheManagerUtils.buildCacheManager();
}

此时构造CacheManager 是会之下到以下代码this

产生这个问题根本的缘由是,shiro每次早于EhCacheCacheConfiguration去构造对象,当shiro中已经构造了cacheMangaer时,后面再重复构造就会抛出异常。debug

异常信息建议中使用静态的create方法,我查看了下CacheManager源代码,实现了一个单例对象

public static CacheManager create(Configuration config) throws CacheException {
    if (singleton != null) {
        LOG.debug("Attempting to create an existing singleton. Existing singleton returned.");
        return singleton;
    } else {
        Class var1 = CacheManager.class;
        synchronized(CacheManager.class) {
            if (singleton == null) {
                singleton = newInstance(config);
            } else {
                LOG.debug("Attempting to create an existing singleton. Existing singleton returned.");
            }

            return singleton;
        }
    }
}

因此在shiro中,使用该方式去构造beanget

因而我想调整shiro的执行顺序,计划经过@AutoConfigureAfter注解让shiro晚于EhCacheCacheConfiguration执行,可是EhCacheCacheConfiguration没有声明public。

后来认真看了下

@ConditionalOnMissingBean

public net.sf.ehcache.CacheManager ehCacheCacheManager() 构造时有ConditionalOnMissingBean ,我只须要在shiro中建立该bean便可。

因而在 shiroConfig中增长

@Bean
@ConditionalOnMissingBean
public net.sf.ehcache.CacheManager ehCacheCacheManager() {
    return CacheManager.create();
}
相关文章
相关标签/搜索