最近參加面試,簡歷上寫了Spring,SpringMVC。然后面試官死磕這部分,當時記憶模糊,當場就hold不住了!事后,我覺得有必要重新翻閱一下SpringMVC的整個執行流程,寫這系列文章,算是對自己的一個小懲罰吧,但為了夢想更進一步,我沒啥怨言!
先來一張大圖做個引導,這系列文章基本也是按照這個圖進行說明:
1.ContextLoaderListner
將SpringMVC,必須先從web.xml開始講起,從配置ContextLoaderListner開始,圖中所示:
平時我們直接使用Spring做項目的時候是通過ClassPathXmlApplicationContext這種方式去加載Spring的配置文件,而對于web項目不同,我們得想辦法將配置文件的路徑以context-param的方式加載并且使用ContextLoaderListner進行監聽讀取;ContextLoaderListner的作用就是在啟動web容器的時候,自動裝配ApplicationContext的配置信息,看一眼ContextLoaderListner的構造你就明白了;
從圖中可知,ContextLoaderListner實現了ServletContextListener這個接口,而每個應用都有一個ServletContext的全局對象與之關聯,這個ServletContext對象在應用啟動時被創建,在程序關閉時被銷毀;因此,提前劇透下,ServletContextListener的核心就是初始化WebApplicationContext實例,并將其放值在ServletContext這個全局對象中。
這個地方,可以深入想一下,如果要定義我們自己的ContextListner類,我們完全可以實現ServletContextListener或者繼承ContextLoaderListner來做。
言歸正傳,回到ContextLoaderListner。ServletContext啟動之后會調用ServletContextListener#contextInitialized,因此又回到了下圖中所示內容:
介紹下WebApplicationContext,他其實是ApplicationContext的子接口,為SpringMVC設計的,如圖所示:
繼續往下走,看ContextLoader#initWebApplicationContext實現,說下它的實現邏輯,代碼咋們一步一步貼:
1.首先判端web.xml中是否多次定義了ContextLoaderListner,若是,則直接拋異常;
2.創建WebApplicationContext的實例;
在這個地方要初始化我們的根上下文,它會通過讀取ContextLoader類的目錄下屬性文件ContextLoader.properties,并根據其中的配置實現WebApplicationContext的實現類
ContextLoader.properties中內容如下所示:
3.將webApplicationContext實例set進servletContext中,讓其跟著servletContext同生共死;
4.獲取當前線程對于的ClassLoader,并且將其與創建的context實例放入Map中,做映射;
以上便是對ContextLoaderListner中邏輯的一個講解,其實說到底ContextLoaderListner就做了一件事,初始化WebApplicationContext的具體實例作為IOC容器,關于DispatchServlet的講解請看后面更新;