• springmvc源码之Web上下文初始化


    系列文章目录

    springmvc源码之Web上下文初始化
    springmvc源码之DispatcherServlet前端控制器
    springmvc源码之HandlerMapping处理器映射器



    Web上下文初始化

    web上下文与SerlvetContext的生命周期应该是相同的,springmvc中的web上下文初始化是由ContextLoaderListener来启动的

    在这里插入图片描述

    在web.xml中配置ContextLoaderListener

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
    listener>
    <context-param>
            <param-name>contextConfigLocationparam-name>
            <param-value>classpath:applicationContext.xmlparam-value>
    context-param>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    ContextLoaderListener

    ContextLoaderListener实现了ServletContextListener接口,ServletContextListener是Servlet定义的,提供了与Servlet生命周期结合的回调,contextInitialized方法和contextDestroyed方法;ContextLoaderListener继承了ContextLoader类,通过ContextLoader来完成实际的WebApplicationContext的初始化工作,并将WebApplicationContext存放至ServletContext中,ContextLoader就像是spring应用在web容器中的启动器

    从spring3.x起就不需要配置监听器ContextLoaderListener,只需要配置DispatcherServlet就可以了

    public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
    
       /**
        * Initialize the root web application context.
        */
      // ServletContext被创建时触发,初始化web上下文
       @Override
       public void contextInitialized(ServletContextEvent event) {
          initWebApplicationContext(event.getServletContext());
       }
    
       /**
        * Close the root web application context.
        */
      // ServletContext被销毁时触发,关闭web上下文
       @Override
       public void contextDestroyed(ServletContextEvent event) {
          closeWebApplicationContext(event.getServletContext());
          ContextCleanupListener.cleanupAttributes(event.getServletContext());
       }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    在启动时会创建一个WebApplicationContext作为IOC容器,默认的实现类是XmlWebApplicationContext

    /** Default config location for the root context */
    // 默认的配置位置,如果不进行配置,就会读取这个文件
    public static final String DEFAULT_CONFIG_LOCATION = "/WEB-INF/applicationContext.xml";
    
    /** Default prefix for building a config location for a namespace */
    // 配置文件默认在/WEB-INF/目录下
    public static final String DEFAULT_CONFIG_LOCATION_PREFIX = "/WEB-INF/";
    
    /** Default suffix for building a config location for a namespace */
    // 配置文件默认后缀名是.xml
    public static final String DEFAULT_CONFIG_LOCATION_SUFFIX = ".xml";
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    initWebApplicationContext初始化
    public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
      // WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE是WebApplicationContext.class.getName() + ".ROOT"
      // 如果servletContext中已经存在根上下文属性,则说明已经有一个根上下文存在了
       if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {
          throw new IllegalStateException(
                "Cannot initialize context because there is already a root application context present - " +
                "check whether you have multiple ContextLoader* definitions in your web.xml!");
       }
    
       Log logger = LogFactory.getLog(ContextLoader.class);
       servletContext.log("Initializing Spring root WebApplicationContext");
       
       long startTime = System.currentTimeMillis();
    
       try {
          // Store context in local instance variable, to guarantee that
          // it is available on ServletContext shutdown.
          if (this.context == null) {
            // 初始化context
             this.context = createWebApplicationContext(servletContext);
          }
          if (this.context instanceof ConfigurableWebApplicationContext) {
             ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;
             if (!cwac.isActive()) {
                // The context has not yet been refreshed -> provide services such as
                // setting the parent context, setting the application context id, etc
                if (cwac.getParent() == null) {
                   // The context instance was injected without an explicit parent ->
                   // determine parent for root web application context, if any.
                   ApplicationContext parent = loadParentContext(servletContext);
                   cwac.setParent(parent);
                }
                configureAndRefreshWebApplicationContext(cwac, servletContext);
             }
          }
         // 记录在servletContext中
          servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
    
          ClassLoader ccl = Thread.currentThread().getContextClassLoader();
          if (ccl == ContextLoader.class.getClassLoader()) {
             currentContext = this.context;
          }
          else if (ccl != null) {
             currentContextPerThread.put(ccl, this.context);
          }
    
          
    
          return this.context;
       }
       catch (RuntimeException ex) {
          logger.error("Context initialization failed", ex);
          servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ex);
          throw ex;
       }
       catch (Error err) {
          logger.error("Context initialization failed", err);
          servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, err);
          throw err;
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    创建WebApplicationContext上下文
    protected WebApplicationContext createWebApplicationContext(ServletContext sc) {
      // 如果在web.xml中有配置contextClass,则使用配置的类
      // 如果没有配置,则使用默认的配置 ContextLoader.properties
      // org.springframework.web.context.WebApplicationContext=org.springframework.web.context.support.XmlWebApplicationContext
    
       Class<?> contextClass = determineContextClass(sc);
       if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {
          throw new ApplicationContextException("Custom context class [" + contextClass.getName() +
                "] is not of type [" + ConfigurableWebApplicationContext.class.getName() + "]");
       }
       return (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
  • 相关阅读:
    安全防御,防火墙配置NAT转换智能选举综合实验
    JDBC再回顾
    [附源码]计算机毕业设计JAVA教师业绩考核系统
    华为云云耀云服务器L实例评测|在Docker环境下部署PrestaShop电子商务系统
    JSD-2204-(业务逻辑开发)-开发分类功能-分页查询-Day08
    Python pytorch tensorflow可视化工具Visdom使用教程--堪比TensorboardX
    聚观早报 | 科学家颜宁宣布离美归国;亚马逊市值跌破1万亿美元;快手创作者版App正式上线
    Eureka之使用详解
    温故而知新十(C++)
    vue中插槽的详解
  • 原文地址:https://blog.csdn.net/Lxn2zh/article/details/127961038