zoukankan      html  css  js  c++  java
  • 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的双亲上下文.

  • 相关阅读:
    懒加载——实现原理
    html5shiv.js和respond.min.js
    点击app分享链接,js判断手机是否安装某款app,有就尝试打开,没有就下载
    ajax获取后台数据渲染(整片文章不分段落)解决方案,要使用htmL方式输出
    +-下拉菜单
    html 中a标签的问题(无反应,跳转,调用方法)
    js中两种定时器,setTimeout和setInterval的区别
    chrome 调试进入 paused in debugger 状态解决办法
    mybatis-plus 获取新增id
    linux unzip和zip
  • 原文地址:https://www.cnblogs.com/yulinfeng/p/6758866.html
Copyright © 2011-2022 走看看