这几天在对一个老项目做底层存储迁移,由oracle改为mysql,在此期间发现一个问题,导致tomcat启动报错。
问题描述:本地eclipse启动tomcat发布项目,从日志中可以看到,spring被初始化了四次!由于spring多次初始化,导致资源被重复加载,这将带来一系列问题,比如定时任务执行两次等等,我遇到的两个明显的报错是Druid注册数据源的时候,说已存在的数据源,也就是重复注册了,还有一个是metaq producer group在第二次创建的时候报错,说是之前已经创建过了,上图吧,更直观些;
第一次初始化spring容器:
第二次初始化spring容器:
第二次初始化的时候,德鲁伊(使用了tddl数据库中间件)注册数据源的时候就报错了,从异常的字面意思就很明显的知道,是数当前注册的数据源已经存在,也就是重复注册了;
第二次初始化spring容器引起的metaq生产者组重复创建的异常信息如下:
不要太在意这两个异常,只是spring重复初始化带来的问题的两个小例子,其实这两个问题不影响项目正常运行,metaq这个异常其实在刚集成metaq的时候就已经发现了,而且也知道是因为spring初始化两次引起的,因为小伙伴的惰性,时间因素及不影响正常运行,就没有去深究初始化两次的原因,就像开发答应产品“该功能在二期会实现”一样,然后就没有然后了。。。然而这次数据库切换,又冒出来了一个报错,这样下去不行的,还是解决了吧。
排查过程:
1、首先想到是否spring配置有问题,经排查没有问题。
2、发到开发服务器上看下,噢,有发现,本地eclipse中启动tomcat的初始化四次,而发布到服务器上变成了两次。
那么本地直接发不到tomcat下面呢,不经过eclipse,直接打成war包,扔到tomcat webapps目录下,不改任何配置,直接启动,嗯,有点意思,初始化了两次,那么其中的两次初始化就是在eclipse上启动tomcat引起的了,虽然缩小了范围,但是没遇到过这种问题呢,为什么在eclipse中启动会初始化两次,真心不知道,求助万能的度娘(不要鄙视我,不是不用谷歌,是懒得翻墙,度娘能解决的何必那么麻烦),还挺好使,因为我把
项目的context root改成了/,我又习惯于把tomcat的发布目录改为webapps目录
,如下图:
这样,tomcat启动的时候,先发布一次webpps下面的/xxx,然后再发布一次/,所以发布了两次,spring自然就被初始化了两次
,问题找到了,怎么解决呢:
网上有多种解决方法,只说
一种简单有效的办法,tomcat发布目录,改在其他目录,不要发布在webapps目录下
,就是这么简单:
改完之后,再启动,初始化四次,变成了两次,还有两次,继续排查。。。
3、spring配置没有问题,因为没有方向,万能的度娘也帮不上忙了,怎么办?
开启debug级别日志看看,看下初始化过程!为什么一开始没有开debug日志呢,因为我还是比较讨厌debug日志的,打的日志太多太多,很容易掩盖想要看的信息,但是不得不承认,它是一个很好的排查问题的手段!果然有惊喜:
按顺序初始化Filter的时候,发现初始化sessionFilter,竟然引起了spring的初始化,看来问题就在这了,为什么会引起spring初始化呢,打开这个过滤器的初始化代码看一下:
呵呵 ..呵呵..呵呵!
相信大家都知道怎么回事了!日志中也打印了有相关信息,
new ClassPathXmlApplicationContext
("spring/application_context_service.xml")
;
代码中直接加载了一遍spring!
怎么改呢:网上各种方式,总的方向就是从已有的容器中获取想要的bean,这里给个链接http://blog.csdn.net/budapest/article/details/38493003,感谢博主,本文不在重复造轮子。
但是网上的各种方式,对Filter来说,并没有什么卵用(试了各种方法),因为filter加载的时候,还没有初始化spring。我的解决方法是把Filter换成了springmvc的拦截器,因为恰好用的springmvc,想要的bean,直接作为属性注进去,不然的话还真不知道怎么解决,望大侠指点迷津。
到此结束,内容有点啰嗦,没有直接针对问题和解决方法,只是想为新手传达一些排查问题的思路。
第一篇博客,希望以后能够养成习惯!
@Autowired注入的对象执行方法报空指针
为什么,正常来说是有这个对象的,输出相关日志发现在用到一些变量的时候会导致这个
问题
。
那就是加了@Service,@Controller,@Component的注解后的类的静态属性,(也就是加了static关键字,属于这个类的成员变量)。
为什么呢?
因为
Spring
启动以后,
初始化
容器
的时候,会先把加了@Component,@Bean,@Service,@Controller,@Repository注解的类,加入到
Spring
的
初始化
容器
中
,
那么就会加载到
问题
描述
    项目
中
使用quartz创建了一个定时任务,在系统启动后立即执行,我发现项目在启动
过程
中
,会执行4次这个定时任务,也就是说项目被
初始化
了4次,这样会导致与任务相关的点出
问题
    最初我是现从精简
Spring
与
Spring
MVC的配置开始入手
解决
这个
问题
的,精简完成后由
初始化
4次降为了两次,后来又通过配置tomcat将初...
以下是工作
过程
中
常见的一些
Spring
容器
启动时错误整理,方便后期再次遇到的时候,能够快速查询。本文章将不定时长期更新
1、NoSuchBeanDefinitionException
org.
spring
framework.beans.factory.BeanCreationException:Error creating bean with name 'xxx.xxx.xxx': Inje...
30-Nov-2021 20:28:15.419 严重 [RMI TCP Connection(2)-127.0.0.1] org.apache.catalina.core.ContainerBase.removeChild ContainerBase.removeChild: destroy:
org.apache.catalina.LifecycleException: An invalid Lifecycle transition was attempted ([before..
1. 加载配置文件:
Spring
通过读取配置文件(如 XML 文件或注解)来获取有关 bean 的信息。
2. 创建 BeanFactory
容器
:
Spring
使用 BeanFactory 接口来创建一个
容器
,该
容器
用于管理 bean。
3. 向
容器
注册 Bean:在
容器
中
注册所有的 bean。
4. Bean 实例化:
Spring
容器
调用每个 bean 的构造函数,创建 bean 的实例。
5. Bean 依赖注入:在 bean 实例创建后,
Spring
容器
负责为每个 bean 设置其所需的依赖。
6. Bean
初始化
:在所有的依赖被注入后,
Spring
容器
调用 bean 的
初始化
方法(如使用 @PostConstruct 注解的方法),使 bean 可以开始提供服务。
这些步骤构成了
Spring
中
的 bean
初始化
过程
。