這篇文章給大家介紹如何進(jìn)行Spring源代碼解析IoC容器在Web容器中的啟動(dòng),內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對(duì)大家能有所幫助。
創(chuàng)新互聯(lián)建站專注于禪城網(wǎng)站建設(shè)服務(wù)及定制,我們擁有豐富的企業(yè)做網(wǎng)站經(jīng)驗(yàn)。 熱誠(chéng)為您提供禪城營(yíng)銷型網(wǎng)站建設(shè),禪城網(wǎng)站制作、禪城網(wǎng)頁(yè)設(shè)計(jì)、禪城網(wǎng)站官網(wǎng)定制、微信小程序服務(wù),打造禪城網(wǎng)絡(luò)公司原創(chuàng)品牌,更為您提供禪城網(wǎng)站排名全網(wǎng)營(yíng)銷落地服務(wù)。
在web容器中,通過(guò)ServletContext為Spring的IOC容器提供宿主環(huán)境,對(duì)應(yīng)的建立起一個(gè)IOC容器的體系。其中,首先需要建立的是根上下文,這個(gè)上下文持有的對(duì)象可以有業(yè)務(wù)對(duì)象,數(shù)據(jù)存取對(duì)象,資源,事物管理器等各種中間層對(duì)象。在這個(gè)上下文的基礎(chǔ)上,和web MVC相關(guān)還會(huì)有一個(gè)上下文來(lái)保存控制器之類的MVC對(duì)象,這樣就構(gòu)成了一個(gè)層次化的上下文結(jié)構(gòu)。在web容器中啟動(dòng)Spring應(yīng)用程序就是一個(gè)建立這個(gè)上下文體系的過(guò)程。Spring為web應(yīng)用提供了上下文的擴(kuò)展接口
WebApplicationContext:
Java代碼
而一般的啟動(dòng)過(guò)程,Spring會(huì)使用一個(gè)默認(rèn)的實(shí)現(xiàn),XmlWebApplicationContext - 這個(gè)上下文實(shí)現(xiàn)作為在web容器中的根上下文容器被建立起來(lái),具體的建立過(guò)程在下面我們會(huì)詳細(xì)分析。
Java代碼
對(duì)于一個(gè)Spring激活的web應(yīng)用程序,可以通過(guò)使用Spring代碼聲明式的指定在web應(yīng)用程序啟動(dòng)時(shí)載入應(yīng)用程序上下文(WebApplicationContext),Spring的ContextLoader是提供這樣性能的類,我們可以使用 ContextLoaderServlet或者ContextLoaderListener的啟動(dòng)時(shí)載入的Servlet來(lái)實(shí)例化Spring IOC容器 - 為什么會(huì)有兩個(gè)不同的類來(lái)裝載它呢,這是因?yàn)樗鼈兊氖褂眯枰獏^(qū)別不同的Servlet容器支持的Serlvet版本。但不管是 ContextLoaderSevlet還是 ContextLoaderListener都使用ContextLoader來(lái)完成實(shí)際的WebApplicationContext的初始化工作。這個(gè)ContextLoder就像是Spring Web應(yīng)用程序在Web容器中的加載器booter。當(dāng)然這些Servlet的具體使用我們都要借助web容器中的部署描述符來(lái)進(jìn)行相關(guān)的定義。
下面我們使用ContextLoaderListener作為載入器作一個(gè)詳細(xì)的分析,這個(gè)Servlet的監(jiān)聽器是根上下文被載入的地方,也是整個(gè) Spring web應(yīng)用加載上下文的第一個(gè)地方;從加載過(guò)程我們可以看到,首先從Servlet事件中得到ServletContext,然后可以讀到配置好的在web.xml的中的各個(gè)屬性值,然后ContextLoder實(shí)例化WebApplicationContext并完成其載入和初始化作為根上下文。當(dāng)這個(gè)根上下文被載入后,它被綁定到web應(yīng)用程序的ServletContext上。任何需要訪問該ApplicationContext的應(yīng)用程序代碼都可以從WebApplicationContextUtils類的靜態(tài)方法來(lái)得到:
Java代碼
WebApplicationContext getWebApplicationContext(ServletContext sc)
以Tomcat作為Servlet容器為例,下面是具體的步驟:
1.Tomcat 啟動(dòng)時(shí)需要從web.xml中讀取啟動(dòng)參數(shù),在web.xml中我們需要對(duì)ContextLoaderListener進(jìn)行配置,對(duì)于在web應(yīng)用啟動(dòng)入口是在ContextLoaderListener中的初始化部分;從Spring MVC上看,實(shí)際上在web容器中維護(hù)了一系列的IOC容器,其中在ContextLoader中載入的IOC容器作為根上下文而存在于 ServletContext中。
Java代碼
通過(guò)ContextLoader建立起根上下文的過(guò)程,我們可以在ContextLoader中看到:
Java代碼
建立根上下文的父上下文使用的是下面的代碼,取決于在web.xml中定義的參數(shù):locatorFactorySelector,這是一個(gè)可選參數(shù):
Java代碼
得到根上下文的父上下文以后,就是根上下文的創(chuàng)建過(guò)程:
Java代碼
初始化根ApplicationContext后將其存儲(chǔ)到SevletContext中去以后,這樣就建立了一個(gè)全局的關(guān)于整個(gè)應(yīng)用的上下文。這個(gè)根上下文會(huì)被以后的DispatcherServlet初始化自己的時(shí)候作為自己ApplicationContext的父上下文。這個(gè)在對(duì) DispatcherServlet做分析的時(shí)候我們可以看看到。
3.完成對(duì)ContextLoaderListener的初始化以后, Tomcat開始初始化DispatchServlet,- 還記得我們?cè)趙eb.xml中隊(duì)載入次序進(jìn)行了定義。DispatcherServlet會(huì)建立自己的ApplicationContext,同時(shí)建立這個(gè)自己的上下文的時(shí)候會(huì)從ServletContext中得到根上下文作為父上下文,然后再對(duì)自己的上下文進(jìn)行初始化,并最后存到 ServletContext中去供以后檢索和使用。
可以從DispatchServlet的父類FrameworkServlet的代碼中看到大致的初始化過(guò)程,整個(gè)ApplicationContext的創(chuàng)建過(guò)程和ContextLoder創(chuàng)建的過(guò)程相類似:
Java代碼
對(duì)initWebApplicationContext()調(diào)用的代碼如下:
Java代碼
其中我們看到調(diào)用了WebApplicationContextUtils的靜態(tài)方法得到根ApplicationContext:
Java代碼
4. 然后就是DispatchServlet中對(duì)Spring MVC的配置過(guò)程,首先對(duì)配置文件中的定義元素進(jìn)行配置 - 請(qǐng)注意這個(gè)時(shí)候我們的WebApplicationContext已經(jīng)建立起來(lái)了,也意味著DispatcherServlet有自己的定義資源,可以需要從web.xml中讀取bean的配置信息,通常我們會(huì)使用單獨(dú)的xml文件來(lái)配置MVC中各個(gè)要素定義,這里和web容器相關(guān)的加載過(guò)程實(shí)際上已經(jīng)完成了,下面的處理和普通的Spring應(yīng)用程序的編寫沒有什么太大的差別,我們先看看MVC的初始化過(guò)程:
Java代碼
5. 這樣MVC的框架就建立起來(lái)了,DispatchServlet對(duì)接受到的HTTP Request進(jìn)行分發(fā)處理由doService()完成,具體的MVC處理過(guò)程我們?cè)赿oDispatch()中完成,其中包括使用Command模式建立執(zhí)行鏈,顯示模型數(shù)據(jù)等,這些處理我們都可以在DispatcherServlet的代碼中看到:
Java代碼
實(shí)際的請(qǐng)求分發(fā)由doDispatch(request,response)來(lái)完成:
Java代碼
這樣具體的MVC模型的實(shí)現(xiàn)就由bean配置文件里定義好的view resolver,handler這些類來(lái)實(shí)現(xiàn)用戶代碼的功能。
總結(jié)上面的過(guò)程,我們看到在web容器中,ServletContext可以持有一系列的web上下文,而在整個(gè)web上下文中存在一個(gè)根上下文來(lái)作為其它 Servlet上下文的父上下文。這個(gè)根上下文是由ContextLoader載入并進(jìn)行初始化的,對(duì)于我們的web應(yīng)用, DispatcherSerlvet載入并初始化自己的上下文,這個(gè)上下文的父上下文是根上下文,并且我們也能從ServletContext中根據(jù) Servlet的名字來(lái)檢索到我們需要的對(duì)應(yīng)于這個(gè)Servlet的上下文,但是根上下文的名字是由Spring唯一確定的。這個(gè) DispactcherServlet建立的上下文就是我們開發(fā)Spring MVC應(yīng)用的IOC容器。
關(guān)于如何進(jìn)行Spring源代碼解析IoC容器在Web容器中的啟動(dòng)就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。