生产中遇到的Spring项目Bean的多次加载问题
问题现象#
最近在本地调试公司的一个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:
作者:MindForward
出处:https://www.cnblogs.com/mindforward/p/16795266.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
微信公众号:时钟在说话
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!