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:
- Use one of the CacheManager.create() static factory methods to reuse same CacheManager with same name or create one if necessary
- 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(); }