Spring boot热部署导致CacheManager重名的解决办法

前言

最近博主在搭建Spring boot框架,但是有点小问题。由于pom.xml中添加了
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
热部署依赖,导致修改控制层或业务层代码之后,应用重启。但是重启过程失败,一直报错缓存重复。报错如下:

Caused by: net.sf.ehcache.CacheException: Another CacheManager with same name 'es' 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.
The source of the existing CacheManager is: DefaultConfigurationSource [ ehcache.xml or ehcache-failsafe.xml ]
    at net.sf.ehcache.CacheManager.assertNoCacheManagerExistsWithSameName(CacheManager.java:460)
    at net.sf.ehcache.CacheManager.init(CacheManager.java:349)
    at net.sf.ehcache.CacheManager.<init>(CacheManager.java:237)
    at org.springframework.cache.ehcache.EhCacheManagerUtils.buildCacheManager(EhCacheManagerUtils.java:54)
    at org.springframework.cache.ehcache.EhCacheCacheManager.afterPropertiesSet(EhCacheCacheManager.java:74)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1687)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1624)
    ... 109 common frames omitted

前面还有许多其他错误,都是由于定义CacheManager 这个bean导致其他定义的bean加载出错。
PS:
1、ehcache.xml这个文件除了我自己创建的以外,依赖的shiro-ehcache-1.4.0.jar中也有。
2、ehcache-failsafe.xml这个文件在依赖的ehcache-core-2.5.0.jar中(我未创建)。

解决方法

在网上找了许多相应的办法,有说和ehcache-core包版本在2.5.0以后有关,也有说是没有setShared(true)有关,也有说和isSingleton有关。博主都改过来了,但是都不起作用。昨天偶然发现可能与热部署有关,终于找到一篇相关的博文下面别人的评论,链接如下:热部署缓存出错看评论!他的解决方案如下:

这个问题解决了!按如下方法:
1、在ShiroConfiguration中添加如下bean,用它来管理EhCacheManager的生命周期
@Bean(name = "lifecycleBeanPostProcessor")
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
logger.info("ShiroConfiguration--lifecycleBeanPostProcessor");
return new LifecycleBeanPostProcessor();
}
2、在EhCacheManager 上添加如下信息:@DependsOn("lifecycleBeanPostProcessor")

@Bean
@DependsOn("lifecycleBeanPostProcessor")
public EhCacheManager shiroEhcacheManager() {
logger.info("ShiroConfiguration--ehCacheManager");

EhCacheManager shiroEhcacheManager = new EhCacheManager();

shiroEhcacheManager.setCacheManagerConfigFile("classpath:ehcache-shiro.xml");

return shiroEhcacheManager;
}

但是我测试并不成功!!!所以又去看了其他的博客,差不多把相关的都看了,最终发现其实我漏掉了以前看的一种方法,链接如下:请看第二种方法!由于我是SSM框架转Spring boot,以前都是xml的配置文件,现在改为由class定义bean,重启应用的时候可能不会自动销毁已存在的CacheManager,需要在定义bean的方法中判断一下。我和上图链接中的有点不一样,有好几个cache的bean,我原来的如下(错误):

@Bean(name = "ehcacheManager")
    public CacheManager ehCacheManagerFactoryBean() {
        EhCacheManagerFactoryBean bean=new EhCacheManagerFactoryBean();
         //添加XML目录
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        try {
            bean.setConfigLocation(resolver.getResource("classpath:ehcache.xml"));
            bean.setShared(true);
            bean.isSingleton();
            return bean.getObject();
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    @Bean(name = "springCacheManager")
    public EhCacheCacheManager cacheCacheManagerBean() {
        EhCacheCacheManager bean=new EhCacheCacheManager();
        bean.setCacheManager(ehCacheManagerFactoryBean());
        return bean;
    }

    @Bean(name = "cacheManager")
    public SpringCacheManagerWrapper springCacheManagerWrapperBean() {
        SpringCacheManagerWrapper bean=new SpringCacheManagerWrapper();
        bean.setCacheManager(cacheCacheManagerBean());
        return bean;
    }

正确的方法是将@Bean(name = “ehcacheManager”)的方法改为如下:

    @Bean(name = "ehcacheManager")
    public CacheManager ehCacheManagerFactoryBean() {
          CacheManager cacheManager = CacheManager.getCacheManager("es");
            if(cacheManager == null){
                try {
                    cacheManager = CacheManager.create(ResourceUtils.getInputStreamForPath("classpath:ehcache.xml"));
                } catch (IOException e) {
                    throw new RuntimeException("initialize cacheManager failed");
                }
            }
           return cacheManager;
    }

es是我创建的ehcache.xml中定义的ehcache名称!!

至此问题解决!!!!

结语

Spring boot的热部署很好用,以前一般手动开应用要20多秒,现在修改好这个问题之后,自动重启应用只需要几秒!!!虽然我一直知道是重启应用时重复导致的,但只想到在定义bean的时候先销毁(启动报错),没有想到这样做判断!总的来说还是不知道CacheManager cacheManager = CacheManager.getCacheManager("es");这样初始化!

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值