Spring和SpringMVC配置中父子WebApplicationContext的關系


一、前言

  有這么一個故事:一輛裝滿石頭的板車,一根繩子系着,起初繩子沒有拉直,拉繩的人以為很輕,等真的綳直了才發現自己的力氣根本不夠~人往往喜歡得過且過,但是有些東西真的是繞不過的,所以現在必須努力的武裝自己......今天開講的就是ServletContext和Spring的ApplicationContext以及每個SpringMVC中的上下文關系~

二、正文

  注明:以下內容沒有用斜體表示的類,都是實際的類,不是偽代碼!

  如果對“上下文”不太了解的,我這邊說下,程序里面所謂的“上下文”就是程序的執行環境,打個比方:你有家吧?如果家都沒有就別學編程了,租的也行啊!你就相當於web程序,家就相當於web程序的上下文,你可以在家里放東西,也可以取東西,你的衣食住行都依賴這個家,這個家就是你生活的上下文環境~

ServletContext:

  首先說說ServletContext這個web應用級的上下文。web容器(比如tomcat、jboss、weblogic等)啟動的時候,它會為每個web應用程序創建一個ServletContext對象 它代表當前web應用的上下文(注意:是每個web應用有且僅創建一個ServletContext,一個web應用,就是你一個web工程)。一個web中的所有servlet共享一個ServletContext對象,所以可以通過ServletContext對象來實現Servlet之間的通訊。在一個繼承自HttpServlet對象的類中,可以通過this.getServletContext來獲取。

ApplicationContext:

  接下來說說在web應用中spring的上下文。在web程序中使用spring的時候,我們需要配置(筆者使用的spring版本為4.0.2):

<listener>  
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>  
 </listener>  

  在web容器啟動時,會觸發容器初始化事件,此時ContextLoaderListener會監聽到這個事件,其contextInitialized方法會被調用,在這個方法中,spring會初始化一個啟動上下文,這個上下文被稱為根上下文,即WebApplicationContext,這是一個接口(這個接口繼承ApplicationContext這個接口),確切的說,其實際的實現類是XmlWebApplicationContext。這個就是Spring的IoC容器,其對應的Bean定義的配置由web.xml中的context-param標簽指定。在這個IoC容器初始化完畢后,Spring以WebApplicationContext.ROOTWEBAPPLICATIONCONTEXTATTRIBUTE為屬性Key,將其存儲到ServletContext中,便於獲取。

[servletContext]:(這邊用斜體表示,以防與ServletContext混淆,這邊這個其實是指每個HttpServlet都有一個與自己對應的上下文

  再次,contextLoaderListener監聽器初始化完畢后,開始初始化web.xml中配置的Servlet,這個servlet可以配置多個,以最常見的DispatcherServlet為例,這個servlet實際上是一個標准的前端控制器,用以轉發、匹配、處理每個servlet請求。DispatcherServlet上下文在初始化的時候會建立自己的IoC上下文,用以持有spring mvc相關的bean。在建立DispatcherServlet自己的IoC上下文時,會利用WebApplicationContext.ROOTWEBAPPLICATIONCONTEXTATTRIBUTE先從ServletContext中獲取之前的根上下文(即WebApplicationContext)作為自己上下文的parent上下文(有個parent屬性作為對Spring的ApplicationContext的引用)。有了這個parent上下文之后,再初始化自己持有的上下文。這個DispatcherServlet初始化自己上下文的工作在其initStrategies方法中可以看到,大概的工作就是初始化處理器映射、視圖解析等。這個servlet自己持有的上下文默認實現類也是xmlWebApplicationContext。初始化完畢后,spring以與servlet的名字相關(此處不是簡單的以servlet名為Key,而是通過一些轉換,具體可自行查看源碼)的屬性為屬性Key,也將其存到ServletContext中,以便后續使用。這樣每個servlet就持有自己的上下文,即擁有自己獨立的bean空間,同時各個servlet共享相同的bean,即根上下文(第2步中初始化的上下文)定義的那些bean。(但是如何獲取本身的這個[servletContext]呢?筆者這邊比較困惑,難道這邊原作者寫的有誤嗎?

三、鏈接

  https://segmentfault.com/q/1010000000210417

  http://www.educity.cn/wenda/368976.html

 

四、聯系本人

  如有對文章內容不理解的,又沒有博客園賬號的,歡迎加入小生建的企鵝群(純討論,不牽扯任何利益關系):261746360,小杜比亞-博客園


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM