Spring——Web應用中的IoC容器創建(WebApplicationContext根應用上下文的創建過程)


基於Spring-4.3.7.RELEASE

Spring的配置不僅僅局限在XML文件,同樣也可以使用Java代碼來配置。在這里我使用XML配置文件的方式來粗略地講講WebApplicationContext。

一提到Spring,首先就應該能想到的是IoC和AOP,什么是IoC、AOP不在這里做講解。Spring提供一個最為基礎的IoC容器——BeanFactory,但這個IoC容器所能提供給我們的功能比較少,所以我們通常選用另一個——ApplicationContext(應用上下文)來作為我們的IoC容器,其實ApplicationContext也是繼承自BeanFactory,只是在BeanFactory接口基礎上做了擴展。那我們這篇文章里要提到的WebApplicationContext不難猜測出它是ApplicationContext的一個實現,在Web應用中我們就利用WebApplicationContext作為我們的IoC容器。

在Web應用中要使用Spring的IoC容器,首要問題就是如何將IoC容器加載到Web容器中。以下是web.xml的部分配置:

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

這段配置意為給Servlet新增一個監聽器,這個監聽器需要實現ServletContextListener接口,該接口中有兩個方法:

public interface ServletContextListener extends EventListener {
    public void contextInitialized(ServletContextEvent sce);  //ServletContext初始化的時候執行此方法
    public void contextDestroyed(ServletContextEvent sce);  //ServletContext銷毀的時候執行此方法
}

接着來看ContextLoaderListener:

public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
    public ContextLoaderListener() {
    }

    public ContextLoaderListener(WebApplicationContext context) {
        super(context);
    }

    public void contextInitialized(ServletContextEvent event) {
        this.initWebApplicationContext(event.getServletContext());
    }

    public void contextDestroyed(ServletContextEvent event) {
        this.closeWebApplicationContext(event.getServletContext());
        ContextCleanupListener.cleanupAttributes(event.getServletContext());
    }
}

從ContextLoaderListener可以看出WebApplicationContext的初始化實際上是由ContextListener完成的:public void initWebApplicationContext(ServletContext servletContext) 

 

 1 public void initWebApplicationContext(ServletContext servletContext) 
 2     ......
 3     if(this.context == null) {
 4         this.context = this.createWebApplicationContext(servletContext);    //創建根上下文,在這之前會檢查是否已經存在,如果存在則拋出IllegalStateExcpetion異常,跳到第22行
 5     }
 6     ......
 7     if(this.context instanceof ConfigurableWebApplicationContext) {    
 8         ConfigurableWebApplicationContext err = (ConfigurableWebApplicationContext)this.context;
 9         if(!err.isActive()) {
10             if(err.getParent() == null) {
11                 ApplicationContext elapsedTime = this.loadParentContext(servletContext);
12                 err.setParent(elapsedTime);
13             }
14         this.configureAndRefreshWebApplicationContext(err, servletContext);    //ApplicationContext上下文創建好后對其進行賦值和初始化,跳到第31行
15         }
16     }
17     //將WebApplicationContext根上下文綁定到Web應用程序的ServletContext上.
18     servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
19     .....
20      return this.context;
21 }
22 protected WebApplicationContext createWebApplicationContext(ServletContext sc) {
23     Class contextClass = this.determineContextClass(sc);    //判斷使用什么樣的類在Web容器中作為IoC容器,跳到第26行
24     ......
25 }
26 protected Class<?> determineContextClass(ServletContext servletContext) {
27     String contexClassName = servlet.getInitParameter(CONTEXT_CLASS_PARAM);    //讀取web.xml中的配置<context-param>contextClass</context-param>
28     //如果配置了需要使用的CONTEXT_CLASS,那就是用這個class,如果沒有額外的配置,就是用默認的ContextClass也就是XmlWebApplicationContext.
29 }
30 //設置IoC容器的參數,並通過refresh啟動容器的初始化
31 protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc){
32     String configLocationParam;
33 if(ObjectUtils.identityToString(wac).equals(wac.getId())) {
34     configLocationParam = sc.getInitParameter("contextId");
35     if(configLocationParam != null) {
36         wac.setId(configLocationParam);
37     } else {
38         wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + ObjectUtils.getDisplayString(sc.getContextPath()));
39     }
40 }
41     wac.setServletContext(sc);
42     configLocationParam = sc.getInitParameter(CONFIG_LOCATION_PARAM);    //contextConfigLocation,Spring根應用上下文重要的配置文件,很多bean的定義等等
43     ......
44     wac.refresh();    //啟動容器的初始化
45 }

 以上代碼第27行所述web.xml中配置指定的IoC容器:

<context-param>
    <param-name>contextClass</param-name>
    <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</context-param>

以上代碼第42行所述web.xml中配置指定的IoC容器:

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath*:applicationContext.xml</param-value>
</context-param>

上面這段配置就是自定義要使用的IoC容器而不使用默認的XmlApplicationContext容器.

第7行代碼開始,當ApplicationContext上下文建立起來過后,也就是Web應用中的IoC容器建立起來過后,接下來就是applicationContext設置一些參數例如它的雙親.至此在Web應用環境中的IoC容器就已經完成了初始化,由於要考慮Web容器的環境特別,比如各種參數的設置,所以在上面的代碼能看出首先創建了IoC容器,其次再為容器賦一些參數值,最后還有IoC容器和Web容器SevletContext的結合作為全局應用上下文.在接下來會介紹在啟動Spring MVC時DispatcherServert在進行自己持有的上下文的初始化時,將ApplicationContext根應用上下文設置為DispatcherServlet的雙親上下文.

 


免責聲明!

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



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