問題現象
最近在本地除錯公司的一個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只被初始化了一次:
本文來自博客園,作者:時鐘在說話,轉載請注明原文鏈接:https://www.cnblogs.com/mindforward/p/16795266.html
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/514273.html
標籤:Java
上一篇:day47-JDBC和連接池03
下一篇:Hadoop安裝
