springboot提供缓存注解标签
@Cacheable ,当使用ehcache时,autoconfig机制会根据配置文件自动去初始化bean
而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可解决该问题,没找到完美解决的方法
查看了下源代码
EhCacheCacheConfiguration在
@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 是会之下到如下代码
产生这个问题根本的原因是,shiro每次早于EhCacheCacheConfiguration去构造对象,当shiro中已经构造了cacheMangaer时,后面再重复构造就会抛出异常。
异常信息建议中使用静态的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中,使用该方式去构造bean
于是我想调整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();
}