IoC容器在Web容器中的啟動
WebApplicationContext:
Java程式碼
-
public interface
- //這裡定義的常量用於在ServletContext中存取根上下文
- String ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT";
- ......
- //對WebApplicationContext來說,需要得到Web容器的ServletContext
-
ServletContext getServletContext();
- }
而一般的啟動過程,Spring會使用一個預設的實現,XmlWebApplicationContext - 這個上下文實現作為在web容器中的根上下文容器被建立起來,具體的建立過程在下面我們會詳細分析。
Java程式碼
- public class XmlWebApplicationContext extends AbstractRefreshableWebApplicationContext {
- /** 這是和web部署相關的位置資訊,用來作為預設的根上下文bean定義資訊的存放位置*/
-
public static final String DEFAULT_CONFIG_LOCATION = "/WEB-INF/applicationContext.xml"
- public static final String DEFAULT_CONFIG_LOCATION_PREFIX = "/WEB-INF/";
- public static final String DEFAULT_CONFIG_LOCATION_SUFFIX = ".xml";
- //我們又看到了熟悉的loadBeanDefinition,就像我們前面對IOC容器的分析中一樣,這個載入工程在容器的refresh()的時候啟動。
- protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws IOException {
- //對於XmlWebApplicationContext,當然使用的是XmlBeanDefinitionReader來對bean定義資訊來進行解析
- XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
- beanDefinitionReader.setResourceLoader(this);
- beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
- initBeanDefinitionReader(beanDefinitionReader);
- loadBeanDefinitions(beanDefinitionReader);
- }
- protected void initBeanDefinitionReader(XmlBeanDefinitionReader beanDefinitionReader) {
- }
- //使用XmlBeanDefinitionReader來讀入bean定義資訊
- protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
- String[] configLocations = getConfigLocations();
- if (configLocations != null) {
- for (int i = 0; i < configLocations.length; i++) {
- reader.loadBeanDefinitions(configLocations[i]);
- }
- }
- }
- //這裡取得bean定義資訊位置,預設的地方是/WEB-INF/applicationContext.xml
- protected String[] getDefaultConfigLocations() {
- if (getNamespace() != null) {
- return new String[] {DEFAULT_CONFIG_LOCATION_PREFIX + getNamespace() + DEFAULT_CONFIG_LOCATION_SUFFIX};
- }
- else {
- return new String[] {DEFAULT_CONFIG_LOCATION};
- }
- }
- }
對於一個Spring啟用的web應用程式,可以通過使用Spring程式碼宣告式的指定在web應用程式啟動時載入應用程式上下文(WebApplicationContext),Spring的ContextLoader是提供這樣效能的類,我們可以使用 ContextLoaderServlet或者ContextLoaderListener的啟動時載入的Servlet來例項化Spring IOC容器 - 為什麼會有兩個不同的類來裝載它呢,這是因為它們的使用需要區別不同的Servlet容器支援的Serlvet版本。但不管是 ContextLoaderSevlet還是 ContextLoaderListener都使用ContextLoader來完成實際的WebApplicationContext的初始化工作。這個ContextLoder就像是Spring Web應用程式在Web容器中的載入器booter。當然這些Servlet的具體使用我們都要藉助web容器中的部署描述符來進行相關的定義。
下面我們使用ContextLoaderListener作為載入器作一個詳細的分析,這個Servlet的監聽器是根上下文被載入的地方,也是整個 Spring web應用載入上下文的第一個地方;從載入過程我們可以看到,首先從Servlet事件中得到ServletContext,然後可以讀到配置好的在web.xml的中的各個屬性值,然後ContextLoder例項化WebApplicationContext並完成其載入和初始化作為根上下文。當這個根上下文被載入後,它被繫結到web應用程式的ServletContext上。任何需要訪問該ApplicationContext的應用程式程式碼都可以從WebApplicationContextUtils類的靜態方法來得到:
Java程式碼
- WebApplicationContext getWebApplicationContext(ServletContext sc)
以Tomcat作為Servlet容器為例,下面是具體的步驟:
1.Tomcat 啟動時需要從web.xml中讀取啟動引數,在web.xml中我們需要對ContextLoaderListener進行配置,對於在web應用啟動入口是在ContextLoaderListener中的初始化部分;從Spring MVC上看,實際上在web容器中維護了一系列的IOC容器,其中在ContextLoader中載入的IOC容器作為根上下文而存在於 ServletContext中。
Java程式碼
- //這裡對根上下文進行初始化。
- public void contextInitialized(ServletContextEvent event) {
- //這裡建立需要的ContextLoader
- this.contextLoader = createContextLoader();
- //這裡使用ContextLoader對根上下文進行載入和初始化
- this.contextLoader.initWebApplicationContext(event.getServletContext());
- }
通過ContextLoader建立起根上下文的過程,我們可以在ContextLoader中看到:
Java程式碼
- public WebApplicationContext initWebApplicationContext(ServletContext servletContext)
- throws IllegalStateException, BeansException {
- //這裡先看看是不是已經在ServletContext中存在上下文,如果有說明前面已經被載入過,或者是配置檔案有錯誤。
- if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {
- //直接丟擲異常
- .........
- }
- ...............
- try {
- // 這裡載入根上下文的父上下文
- ApplicationContext parent = loadParentContext(servletContext);
- //這裡建立根上下文作為整個應用的上下文同時把它存到ServletContext中去,注意這裡使用的ServletContext的屬性值是
- //ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,以後的應用都是根據這個屬性值來取得根上下文的 - 往往作為自己上下文的父上下文
- this.context = createWebApplicationContext(servletContext, parent);
- servletContext.setAttribute(
- WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
- ..........
- return this.context;
- }
- ............
- }
建立根上下文的父上下文使用的是下面的程式碼,取決於在web.xml中定義的引數:locatorFactorySelector,這是一個可選引數:
Java程式碼
- protected ApplicationContext loadParentContext(ServletContext servletContext)
- throws BeansException {
- ApplicationContext parentContext = null;
- String locatorFactorySelector = servletContext.getInitParameter(LOCATOR_FACTORY_SELECTOR_PARAM);
- String parentContextKey = servletContext.getInitParameter(LOCATOR_FACTORY_KEY_PARAM);
- if (locatorFactorySelector != null) {
- BeanFactoryLocator locator = ContextSingletonBeanFactoryLocator.getInstance(locatorFactorySelector);
- ........
- //得到根上下文的父上下文的引用
- this.parentContextRef = locator.useBeanFactory(parentContextKey);
- //這裡建立得到根上下文的父上下文
- parentContext = (ApplicationContext) this.parentContextRef.getFactory();
- }
- return parentContext;
- }
得到根上下文的父上下文以後,就是根上下文的建立過程:
Java程式碼
- protected WebApplicationContext createWebApplicationContext(
- ServletContext servletContext, ApplicationContext parent) throws BeansException {
- //這裡需要確定我們載入的根WebApplication的型別,由在web.xml中配置的contextClass中配置的引數可以決定我們需要載入什麼樣的ApplicationContext,
- //如果沒有使用預設的。
- Class contextClass = determineContextClass(servletContext);
- .........
- //這裡就是上下文的建立過程
- ConfigurableWebApplicationContext wac =
- (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
- //這裡保持對父上下文和ServletContext的引用到根上下文中
- wac.setParent(parent);
- wac.setServletContext(servletContext);
- //這裡從web.xml中取得相關的初始化引數
- String configLocation = servletContext.getInitParameter(CONFIG_LOCATION_PARAM);
- if (configLocation != null) {
- wac.setConfigLocations(StringUtils.tokenizeToStringArray(configLocation,
- ConfigurableWebApplicationContext.CONFIG_LOCATION_DELIMITERS));
- }
- //這裡對WebApplicationContext進行初始化,我們又看到了熟悉的refresh呼叫。
- wac.refresh();
- return wac;
- }
初始化根ApplicationContext後將其儲存到SevletContext中去以後,這樣就建立了一個全域性的關於整個應用的上下文。這個根上下文會被以後的DispatcherServlet初始化自己的時候作為自己ApplicationContext的父上下文。這個在對 DispatcherServlet做分析的時候我們可以看看到。
3.完成對ContextLoaderListener的初始化以後, Tomcat開始初始化DispatchServlet,- 還記得我們在web.xml中隊載入次序進行了定義。DispatcherServlet會建立自己的ApplicationContext,同時建立這個自己的上下文的時候會從ServletContext中得到根上下文作為父上下文,然後再對自己的上下文進行初始化,並最後存到 ServletContext中去供以後檢索和使用。
可以從DispatchServlet的父類FrameworkServlet的程式碼中看到大致的初始化過程,整個ApplicationContext的建立過程和ContextLoder建立的過程相類似:
Java程式碼
- protected final void initServletBean() throws ServletException, BeansException {
- .........
- try {
- //這裡是對上下文的初始化過程。
- this.webApplicationContext = initWebApplicationContext();
- //在完成對上下文的初始化過程結束後,根據bean配置資訊建立MVC框架的各個主要元素
- initFrameworkServlet();
- }
- ........
- }
對initWebApplicationContext()呼叫的程式碼如下:
Java程式碼
- protected WebApplicationContext initWebApplicationContext() throws BeansException {
- //這裡呼叫WebApplicationContextUtils靜態類來得到根上下文
- WebApplicationContext parent = WebApplicationContextUtils.getWebApplicationContext(getServletContext());
- //建立當前DispatcherServlet的上下文,其上下文種類使用預設的在FrameworkServlet定義好的:DEFAULT_CONTEXT_CLASS = XmlWebApplicationContext.class;
- WebApplicationContext wac = createWebApplicationContext(parent);
- ........
- if (isPublishContext()) {
- //把當前建立的上下文存到ServletContext中去,注意使用的屬性名是和當前Servlet名相關的。
- String attrName = getServletContextAttributeName();
- getServletContext().setAttribute(attrName, wac);
- }
- return wac;
- }
其中我們看到呼叫了WebApplicationContextUtils的靜態方法得到根ApplicationContext:
Java程式碼
- public static WebApplicationContext getWebApplicationContext(ServletContext sc) {
- //很簡單,直接從ServletContext中通過屬性名得到根上下文
- Object attr = sc.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
- .......
- return (WebApplicationContext) attr;
- }
- 然後建立DispatcherServlet自己的WebApplicationContext:
- protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent)
- throws BeansException {
- .......
- //這裡使用了BeanUtils直接得到WebApplicationContext,ContextClass是前面定義好的DEFAULT_CONTEXT_CLASS =
- //XmlWebApplicationContext.class;
- ConfigurableWebApplicationContext wac =
- (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(getContextClass());
- //這裡配置父上下文,就是在ContextLoader中建立的根上下文
- wac.setParent(parent);
- //保留ServletContext的引用和相關的配置資訊。
- wac.setServletContext(getServletContext());
- wac.setServletConfig(getServletConfig());
- wac.setNamespace(getNamespace());
- //這裡得到ApplicationContext配置檔案的位置
- if (getContextConfigLocation() != null) {
-
相關推薦
各種容器與伺服器的區別與聯絡:Servlet容器 WEB容器 Java EE容器 應用伺服器 WEB伺服器 Java EE伺服器
各種容器與伺服器的區別與聯絡 Servlet容器 WEB容器 Java EE容器 應用伺服器 WEB伺服器 Java EE伺服器 平時我們經常看到各種容器名稱:Servlet容器、WEB容器、Java WEB容器、Java EE容器等,還有各種伺服
maven web 專案中啟動報錯 Java.lang.ClassNotFoundException: org.springframework.web.servlet.DispatcherServlet
主要原因是maven專案裡面的jar包嗎,沒有匯入到專案中 maven web 專案中啟動報錯 Java.lang.ClassNotFoundException: org.springframework.web.servlet.DispatcherServlet 錯誤描述: Java.lang.Cl
web專案中啟動一個執行緒,的方法
JavaWeb 服務啟動時,在後臺啟動載入一個執行緒。 目前,我所掌握的一共有兩種方法,第一種是監聽(Listener),第二種是配置隨專案啟動而啟動的Servlet。 下面對這兩種方法做一簡單的介紹,(Mark一下,防止以後急用又忘記了): 1.監聽(Listener) 首先,我們建立
容器 web容器 EJB容器 web伺服器 web應用伺服器
容器: 容器是一種服務呼叫規範框架,J2EE大量運用了容器和元件技術來構建分層的企業級應用。在J2EE規範中,相應的有WEB Container和EJB Container等。容器提供系統級的服務呼叫。 WEB容器: 給處於其中的應用程式元件(
通過自定義URL協議在Web網頁中啟動本地應用程式
在做web應用的時候,我們經常會遇到在web中呼叫本地應用程式的問題,例如在web中點選一個按鈕,然後開啟自己寫的或者別人的應用程式。上網比較留意的同學應該會發現,想qq客服,淘寶的阿里旺旺客服都會有這樣的效果。 下面我主要介紹一種現在主流的處理方法,這種方
IoC容器在Web容器中的啟動
簡單的說,在web容器中,通過ServletContext為Spring的IOC容器提供宿主環境,對應的建立起一個IOC容器的體系。其中,首先需要建立的是根上下文,這個上下文持有的物件可以有業務物件,資料存取物件,資源,事物管理器等各種中間層物件。在這個上下文的基礎上,和w
Spring MVC原理之Spring應用上下文(IoC容器)在Web容器中的啟動分析
Spring IoC是一個獨立的模組,它並不是直接在Web容器中發揮作用的。如果要在Web環境中使用IoC容器,需要Spring為IoC設計一個啟動過程,把IoC容器導人,並在Web容器中建立起來。具體說來,這個啟動過程是和Web容器的啟動過程整合在一起的
在web.xml中配置監聽器來控制ioc容器生命週期
、整合關鍵-在web.xml中配置監聽器來控制ioc容器生命週期 原因: 1、配置的元件太多,需保障單例項 2、專案停止後,ioc容器也需要關掉,降低對記憶體資源的佔用。 專案啟動建立容器,專案停止銷燬容器。 利用ServletContextListener監控專案來控制。 Spring
在Web專案中配置Spring的IOC容器
如果需要在Web專案中使用Spring的IOC容器,可以在Web專案配置檔案web.xml中做出如下配置: <listener> <listener-class>org.springframework.web.context.Contex
如何在Web專案中配置Spring的IOC容器?
如何在Web專案中配置Spring的IOC容器? 如果需要在Web專案中使用Spring的IOC容器,可以在Web專案配置檔案web.xml中做出如下配置: <listener> <listener-class>org.springframework.w
Spring MVC 根應用上下文在Web容器中的啟動及其銷燬
public WebApplicationContext initWebApplicationContext(ServletContext servletContext) { //判斷servletContext是否已有根上下文 if (servletContext.getAttribute(WebApp
web.xml中配置Spring容器隨專案啟動
<!-- 可以讓spring容器隨專案的啟動而建立,隨專案的關閉而銷燬 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListe
在web專案中如何啟動spring容器?
1.在web.xml配置spring配置檔案的資訊 <context-param> <param-name>contextConfigLocation</param-name> <param-value>clas
docker容器中啟動service服務 Failed to get D-Bus connection: Operation not permitted
docker容器中啟動service服務 failed to get d-bus connection: operation not permitted解決方案:啟動時設置參數 --privileged使用該參數,container內的root擁有真正的root權限。否則,container內的root只是
docker中啟動關閉刪除所有的容器命令
讀取 star -a 命令 啟動 表示 docke dock ima docker中 啟動所有的容器命令 docker start $(docker ps -a | awk ‘{ print $1}‘ | tail -n +2) docker中 關閉所有的容器命令 d
web容器向jar中尋找資源
示例程式碼下載地址 https://files.cnblogs.com/files/Mike_Chang/web%E5%AE%B9%E5%99%A8%E5%90%91jar%E4%B8%AD%E5%AF%BB%E6%89%BE%E8%B5%84%E6%BA%90.rar 具體步驟 1、在
Servlet容器Tomcat中web.xml中url-pattern的配置詳解[附帶原始碼分析
轉載 http://www.cnblogs.com/fangjian0423/p/servletContainer-tomcat-urlPattern.html#springmvc Servlet容器Tomcat中web.xml中url-pattern的配置詳解[附帶原始碼分析 目錄 前
Web容器 與Spring容器 啟動
spring容器是如何在web應用中得到應用的,web容器又是如何以及何時啟動spring容器的呢? 話不多說,看web.xml中幾段配置: <!---①從類路徑下載入spring配置
spring-web:在web應用中即使用監聽器建立spring容器物件
spring-web2:在web應用中,使用spring。spring管理Service,Dao物件,而servlet、JSP、監聽器物件是由Tomcat生成的 web專案中使用spring的問題: 1.容器物件建立多次了, 應該是建立一次 (在應用啟動的時候建立一次) 2.容器物件需要
Web容器自動對HTTP請求中引數進行URLDecode處理
如題,在Java中也許很多人都沒有注意到當我們傳送一個http請求時,如果附帶的引數被URLEncode之後,到達web容器之後,開發者獲取到的引數值會自動變成了encode之前的值。這是一個很好的特點,開發者完全可以忽略http的引數是否需要decode這種事,但是