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();
}
相關文章
相關標籤/搜索