这几天在对一个老项目做底层存储迁移,由oracle改为mysql,在此期间发现一个问题,导致tomcat启动报错。

问题描述:本地eclipse启动tomcat发布项目,从日志中可以看到,spring被初始化了四次!由于spring多次初始化,导致资源被重复加载,这将带来一系列问题,比如定时任务执行两次等等,我遇到的两个明显的报错是Druid注册数据源的时候,说已存在的数据源,也就是重复注册了,还有一个是metaq producer group在第二次创建的时候报错,说是之前已经创建过了,上图吧,更直观些;

第一次初始化spring容器:

SpringBoot JPA repositoryBean初始化慢_初始化

第二次初始化spring容器:

SpringBoot JPA repositoryBean初始化慢_tomcat_02

第二次初始化的时候,德鲁伊(使用了tddl数据库中间件)注册数据源的时候就报错了,从异常的字面意思就很明显的知道,是数当前注册的数据源已经存在,也就是重复注册了;

第二次初始化spring容器引起的metaq生产者组重复创建的异常信息如下:

SpringBoot JPA repositoryBean初始化慢_初始化_03

不要太在意这两个异常,只是spring重复初始化带来的问题的两个小例子,其实这两个问题不影响项目正常运行,metaq这个异常其实在刚集成metaq的时候就已经发现了,而且也知道是因为spring初始化两次引起的,因为小伙伴的惰性,时间因素及不影响正常运行,就没有去深究初始化两次的原因,就像开发答应产品“该功能在二期会实现”一样,然后就没有然后了。。。然而这次数据库切换,又冒出来了一个报错,这样下去不行的,还是解决了吧。

排查过程:

1、首先想到是否spring配置有问题,经排查没有问题。

2、发到开发服务器上看下,噢,有发现,本地eclipse中启动tomcat的初始化四次,而发布到服务器上变成了两次。

那么本地直接发不到tomcat下面呢,不经过eclipse,直接打成war包,扔到tomcat webapps目录下,不改任何配置,直接启动,嗯,有点意思,初始化了两次,那么其中的两次初始化就是在eclipse上启动tomcat引起的了,虽然缩小了范围,但是没遇到过这种问题呢,为什么在eclipse中启动会初始化两次,真心不知道,求助万能的度娘,还挺好使,因为我把项目的context root改成了/,我又习惯于把tomcat的发布目录改为webapps目录,如下图:

SpringBoot JPA repositoryBean初始化慢_eclipse_04

SpringBoot JPA repositoryBean初始化慢_tomcat_05

这样,tomcat启动的时候,先发布一次webpps下面的/xxx,然后再发布一次/,所以发布了两次,spring自然就被初始化了两次,问题找到了,怎么解决呢:

网上有多种解决方法,只说一种简单有效的办法,tomcat发布目录,改在其他目录,不要发布在webapps目录下,就是这么简单:

SpringBoot JPA repositoryBean初始化慢_tomcat_06

改完之后,再启动,初始化四次,变成了两次,还有两次,继续排查。。。

3、spring配置没有问题,因为没有方向,万能的度娘也帮不上忙了,怎么办?

开启debug级别日志看看,看下初始化过程!为什么一开始没有开debug日志呢,因为我还是比较讨厌debug日志的,打的日志太多太多,很容易掩盖想要看的信息,但是不得不承认,它是一个很好的排查问题的手段!果然有惊喜:

SpringBoot JPA repositoryBean初始化慢_spring_07

按顺序初始化Filter的时候,发现初始化sessionFilter,竟然引起了spring的初始化,看来问题就在这了,为什么会引起spring初始化呢,打开这个过滤器的初始化代码看一下:

SpringBoot JPA repositoryBean初始化慢_初始化_08

呵呵 ..呵呵..呵呵!

相信大家都知道怎么回事了!日志中也打印了有相关信息,new ClassPathXmlApplicationContext("spring/application_context_service.xml"); 代码中直接加载了一遍spring!

怎么改呢:网上各种方式,总的方向就是从已有的容器中获取想要的bean

但是网上的各种方式,对Filter来说,并没有什么卵用(试了各种方法),因为filter加载的时候,还没有初始化spring。我的解决方法是把Filter换成了springmvc的拦截器,因为恰好用的springmvc,想要的bean,直接作为属性注进去,不然的话还真不知道怎么解决,望大侠指点迷津。

SpringBoot JPA repositoryBean初始化慢_eclipse_09


到此结束,内容有点啰嗦,没有直接针对问题和解决方法,只是想为新手传达一些排查问题的思路。

第一篇博客,希望以后能够养成习惯!