问题现象最近在本地调试公司的一个Web项目时,无意中发现日志中出现了两次同一个服务的init记录,项目都是基于Spring来搭建的 , 按理说服务都是单例的 , 应该只有一次服务加载日志才对,本着对工作认真负责(闲来无事)的态度,必然要一探究竟 。
文章插图
问题分析为什么同一个 Bean 会被容器初始化两次?
首先,我们先来梳理一下 Web 容器中如何加载 Bean:
在 Web 容器中,
ContextLoaderListener
和 DispatchServlet
都会在容器启动的时候加载Bean,区别在于 DispatchServlet
一般会加载 MVC 相关的 Bean , ContextLoaderListener
会加载 Spring 相关的 Bean,二者会分别生成一个WebApplicationContext
。根据 web.xml 的加载顺序,listener 会先于 Servlet 加载,当获取 Bean 时,会优先从
DispatchServlet
生成的 WebApplicationContext
中查找 , 如果找不到再从ContextLoaderListener
生成的 WebApplicationContext
中查找 。那么如果这两个加载了同样的Bean,到底该用谁的呢?
如果二者的配置文件中定义了相同的 Bean , 则实际使用中只会用到
DispatchServlet
中的Bean,ContextLoaderListener
中的 Bean 无法调用,造成内存泄漏 。接下来我们看一下项目中的 web.xml 配置,如下图所示,
ContextLoaderListener
和DispatchServlet
加载了相同的配置 spring.xml,所以会出现两次 Bean 的初始化现象 。文章插图
文章插图
解决方案经过上面的分析,我们知道了,之所以同一个Bean会被加载两次,是由于我们在
DispatchServlet
和ContextLoaderListener
都定义了这个Bean 。因此,我们要做的就是让
ContextLoaderListener
和DispatcherServlet
分别加载不同的Bean:- 新增applicationContext.xml,其中声明ContextLoaderListener要加载的Bean:
文章插图
文章插图
- 修改spring.xml中的包扫描范围,让DispatcherServlet只加载mvc相关的Bean:
文章插图
- 启动服务,查看初始化信息,Service只被初始化了一次:
文章插图
推荐阅读
- 权利法案?1787美国宪法?有何共同意义 美国权利法案的意义
- 手机怎样连接我的电脑(手机怎么访问自己电脑)
- 我的世界中怎么驯服马(马吃什么驯服我的世界)
- 手机连接电脑怎么看手机里的文档(手机用数据线连接电脑)
- 【强烈推荐】用glob库的一行命令显著加速批量读取处理数据
- Docker | dockerfile构建centos镜像,以及CMD和ENTRYPOINT的区别
- Element 前端枚举enum的应用封装
- 如何使用 pyqt 读取串口传输的图像
- 原神兆载怎么让永劫龙兽瘫痪
- 原神3.1阿贝多怎么配队