有這麼一個故事:一輛裝滿石頭的板車,一根繩子繫着,起初繩子沒有拉直,拉繩的人覺得很輕,等真的繃直了才發現本身的力氣根本不夠~人每每喜歡得過且過,可是有些東西真的是繞不過的,因此如今必須努力的武裝本身......今天開講的就是ServletContext和Spring的ApplicationContext以及每一個SpringMVC中的上下文關係~html
註明:如下內容沒有用斜體表示的類,都是實際的類,不是僞代碼!前端
若是對「上下文」不太瞭解的,我這邊說下,程序裏面所謂的「上下文」就是程序的執行環境,打個比方:你有家吧?若是家都沒有就別學編程了,租的也行啊!你就至關於web程序,家就至關於web程序的上下文,你能夠在家裏放東西,也能夠取東西,你的衣食住行都依賴這個家,這個家就是你生活的上下文環境~web
ServletContext:spring
首先說說ServletContext這個web應用級的上下文。web容器(好比tomcat、jboss、weblogic等)啓動的時候,它會爲每一個web應用程序建立一個ServletContext對象 它表明當前web應用的上下文(注意:是每一個web應用有且僅建立一個ServletContext,一個web應用,就是你一個web工程)。一個web中的全部servlet共享一個ServletContext對象,因此能夠經過ServletContext對象來實現Servlet之間的通信。在一個繼承自HttpServlet對象的類中,能夠經過this.getServletContext來獲取。編程
ApplicationContext:segmentfault
接下來講說在web應用中spring的上下文。在web程序中使用spring的時候,咱們須要配置(筆者使用的spring版本爲4.0.2):tomcat
<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中,便於獲取。mvc
[servletContext]:(這邊用斜體表示,以防與ServletContext混淆,這邊這個實際上是指每一個HttpServlet都有一個與本身對應的上下文)this
再次,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]呢?筆者這邊比較困惑,難道這邊原做者寫的有誤嗎?)spa
https://segmentfault.com/q/1010000000210417
http://www.educity.cn/wenda/368976.html
若有對文章內容不理解的,又沒有博客園帳號的,歡迎加入小生建的企鵝羣(純討論,不牽扯任何利益關係):261746360,小杜比亞-博客園