`
jeff2008
  • 浏览: 26112 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

初探spring applicationContext在web容器中加载过程

    博客分类:
  • Java
阅读更多
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
<context-param>
    <param-name>webAppRootKey</param-name>
    <param-value>task.root</param-value>
  </context-param>
  <!-- 定义SPRING配置文件 -->
  
   <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/taskContext*.xml</param-value>
  </context-param>
  

  <context-param>
    <param-name>log4jConfigLocation</param-name>
    <param-value>/WEB-INF/log4j.properties</param-value>
  </context-param>
  <!-- 定义LOG4J监听器 -->
  <listener>
    <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
  </listener>
 
  <!-- 定义SPRING监听器 -->

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

 

进入contextLoaderListener看看到底加载时做了甚么 ==>org.springframework.web.context.ContextLoaderListener

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
public

 class

 ContextLoaderListener implements

 ServletContextListener {

 
  private

 ContextLoader contextLoader;
 
  /**
   * Initialize the root web application context.
   */

//当WEB上下文初始化时,系统会调用此方法

  public

 void

 contextInitialized(ServletContextEvent event) {

    this.contextLoader = createContextLoader();
 

    //监听到WEB上下文初始化的时候执行SPRING上下文contextLoader的初始化工作

    this.contextLoader.initWebApplicationContext(event.getServletContext());


  }

 
  /**
   * Create the ContextLoader to use. Can be overridden in subclasses.
   * @return the new ContextLoader
   */

  protected

 ContextLoader createContextLoader() {

    return

 new

 ContextLoader();
  }

 
  /**
   * Return the ContextLoader used by this listener.
   */

  public

 ContextLoader getContextLoader() {

    return

 contextLoader;
  }

 
  /**
   * Close the root web application context.
   */

  public

 void

 contextDestroyed(ServletContextEvent event) {

    if

 (this.contextLoader != null

) {

      this.contextLoader.closeWebApplicationContext(event.getServletContext());
    }

  }

 
}
 

看一下是怎么来初始化webapplicationContext的 ==>contextLoader.initWebApplicationContext

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
public

 WebApplicationContext initWebApplicationContext(ServletContext servletContext)
      throws

 IllegalStateException, BeansException {

 
    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!"
);
    }

 
    long

 startTime = System.currentTimeMillis();
    if

 (logger.isInfoEnabled()) {

      logger.info("Root WebApplicationContext: initialization started"
);
    }

    servletContext.log("Loading Spring root WebApplicationContext"
);
 
    try

 {

      // Determine parent for root web application context, if any.

      ApplicationContext parent = loadParentContext(servletContext);
 
      // Store context in local instance variable, to guarantee that

      // it is available on ServletContext shutdown.

 

      //创建web上下文

      this.context = createWebApplicationContext(servletContext, parent);
      servletContext.setAttribute(
          WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);


 
      if

 (logger.isInfoEnabled()) {

        logger.info("Using context class ["
 + this.context.getClass().getName() +
            "] for root WebApplicationContext"
);
      }

      if

 (logger.isDebugEnabled()) {

        logger.debug("Published root WebApplicationContext ["
 + this.context +
            "] as ServletContext attribute with name ["
 +
            WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE + "]"
);
      }

      if

 (logger.isInfoEnabled()) {

        long

 elapsedTime = System.currentTimeMillis() - startTime;
        logger.info("Root WebApplicationContext: initialization completed in "
 + elapsedTime + " 

 
ms");

      }

 
      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;
    }

  }
 

==>contextLoader.createWebApplicationContext(servletContext, parent);

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
 protected

 WebApplicationContext createWebApplicationContext(
      ServletContext servletContext, ApplicationContext parent) throws

 BeansException {


    //根据servletContext来决定要实例化的WebApplicationContext

    Class contextClass = determineContextClass(servletContext);
    if

 (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {

      throw

 new

 ApplicationContextException("Custom context class ["
 + contextClass.getName() +
          "] is not of type ConfigurableWebApplicationContext"
);
    }

    ConfigurableWebApplicationContext wac =
        (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
    wac.setParent(parent);
    wac.setServletContext(servletContext);
 
    //得到WEB.XML中设置的SPRING配置文件位置

    String configLocation = servletContext.getInitParameter(CONFIG_LOCATION_PARAM);
    if

 (configLocation != null

) {

      //把配置文件分段后设置到WebApplicationContext的ConfigLocations中

      wac.setConfigLocations(StringUtils.tokenizeToStringArray(configLocation,
          ConfigurableWebApplicationContext.CONFIG_LOCATION_DELIMITERS));
    }

    //刷新WebApplicationContext

    wac.refresh();


    return

 wac;
  }
 

==>contextLoader.determineContextClass(servletContext);

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
protected

 Class determineContextClass(ServletContext servletContext) throws

 ApplicationContextException {


    //获得需要实例化的CONTEXT类名,在web.xml中有设置,如果没有设置,那么为空

    String contextClassName = servletContext.getInitParameter(CONTEXT_CLASS_PARAM);
    if

 (contextClassName != null

) {

      try

 {

        return

 ClassUtils.forName(contextClassName);
      }

      catch

 (ClassNotFoundException ex) {

        throw

 new

 ApplicationContextException(
            "Failed to load custom context class ["
 + contextClassName + "]"
, ex);
      }

    }

    //如果在spring web.xml中没有设置context类位置,那么取得默认context

    else

 {

      //取得defaultStrategies配置文件中的WebApplicationContext属性

      contextClassName = defaultStrategies.getProperty(WebApplicationContext.class.getName());
      try

 {

        return

 ClassUtils.forName(contextClassName);
      }

      catch

 (ClassNotFoundException ex) {

        throw

 new

 ApplicationContextException(
            "Failed to load default context class ["
 + contextClassName + "]"
, ex);
      }

    }



  }
 

SPRING上下文默认的策略是甚么呢? ==>contextLoader.defaultStrategies

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  private

 static

 final

 Properties defaultStrategies;
 
  static

 {

    // Load default strategy implementations from properties file.

    // This is currently strictly internal and not meant to be customized

    // by application developers.

    try

 {


      //设置classpath为contextLoader同级目录

      ClassPathResource resource = new

 ClassPathResource(DEFAULT_STRATEGIES_PATH, ContextLoader.class);
      //加载该目录下的所有properties文件

      defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);


    }

    catch

 (IOException ex) {

      throw

 new

 IllegalStateException("Could not load 'ContextLoader.properties': "
 + ex.getMessage());
    }

  }
 

找到同级目录下的配置文件 ==>ContextLoader.properties

1
2
3
4
5
6
7
8
# Default WebApplicationContext implementation class

 for

 ContextLoader.
# Used as fallback when no explicit context implementation has been specified as context-param.
# Not meant to be customized by application developers.
 

#默认的WebApplicationContext为org.springframework.web.context.support.XmlWebApplicationContext
org.springframework.web.context.WebApplicationContext=org.springframework.web.context.support.XmlWebApplicationContext

 

==>org.springframework.web.context.support.XmlWebApplicationContext

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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
public

 class

 XmlWebApplicationContext extends

 AbstractRefreshableWebApplicationContext {

 
  /** Default config location for the root context */

 

  //配置了默认的spring配置文件

  public

 static

 final

 String DEFAULT_CONFIG_LOCATION = "/WEB-INF/applicationContext.xml"
;


 
  //配置文件默认BUILD路径

  public

 static

 final

 String DEFAULT_CONFIG_LOCATION_PREFIX = "/WEB-INF/"
;
 
  //配置文件默认后缀名

  public

 static

 final

 String DEFAULT_CONFIG_LOCATION_SUFFIX = ".xml"
;
 
  /**
   * Loads the bean definitions via an XmlBeanDefinitionReader.
   * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
   * @see #initBeanDefinitionReader
   * @see #loadBeanDefinitions
   */

  //获得bean配置

  protected

 void

 loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws

 IOException {

    //从BEAN工厂获得一个XmlBeanDefinitionReader 来读取SPRING配置文件

    XmlBeanDefinitionReader beanDefinitionReader = new

 XmlBeanDefinitionReader(beanFactory);
 
    //设置beanDefinitionReader服务于当前CONTEXT

    // resource loading environment.

    beanDefinitionReader.setResourceLoader(this

);
    beanDefinitionReader.setEntityResolver(new

 ResourceEntityResolver(this

));
 
    // Allow a subclass to provide custom initialization of the reader,

    // then proceed with actually loading the bean definitions.

    initBeanDefinitionReader(beanDefinitionReader);

    //读取配置文件

    loadBeanDefinitions(beanDefinitionReader);


  }

 
  /**
   * Initialize the bean definition reader used for loading the bean
   * definitions of this context. Default implementation is empty.
   * <p>Can be overridden in subclasses, e.g. for turning off XML validation
   * or using a different XmlBeanDefinitionParser implementation.
   * @param beanDefinitionReader the bean definition reader used by this context
   * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader#setValidationMode
   * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader#setDocumentReaderClass
   */

  protected

 void

 initBeanDefinitionReader(XmlBeanDefinitionReader beanDefinitionReader) {

  }

 
  /**
   * Load the bean definitions with the given XmlBeanDefinitionReader.
   * <p>The lifecycle of the bean factory is handled by the refreshBeanFactory method;
   * therefore this method is just supposed to load and/or register bean definitions.
   * <p>Delegates to a ResourcePatternResolver for resolving location patterns
   * into Resource instances.
   * @throws org.springframework.beans.BeansException in case of bean registration errors
   * @throws java.io.IOException if the required XML document isn't found
   * @see #refreshBeanFactory
   * @see #getConfigLocations
   * @see #getResources
   * @see #getResourcePatternResolver
   */


  //读取配置文件

  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]);
      }

    }

  }



 
  /**
   * The default location for the root context is "/WEB-INF/applicationContext.xml",
   * and "/WEB-INF/test-servlet.xml" for a context with the namespace "test-servlet"
   * (like for a DispatcherServlet instance with the servlet-name "test").
   */

  //获得默认的ConfigLocations

  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中ApplicationContext加载机制

    在 Web 应用程序中,ApplicationContext 的加载机制是非常重要的, Spring 提供了多种方式来加载 ApplicationContext。 首先,Spring 提供了两种选择来加载 ApplicationContext:ContextLoaderListener 和 ...

    Spring源代码解析(二):IoC容器在Web容器中的启动.doc

    总的来说,Spring在Web容器中的启动过程涉及到`WebApplicationContext`的创建、配置文件的解析、bean定义的加载和bean的实例化。通过这种方式,Spring能够紧密地集成到Web环境中,提供全面的依赖注入和控制反转功能...

    Spring获取ApplicationContext对象工具类的实现方法

    在实际开发过程中,经常需要从各个角落获取到这个ApplicationContext对象,以便于能够使用Spring提供的各种服务。本文将详细介绍Spring中获取ApplicationContext对象的工具类实现方法。 在Spring中,典型的获取...

    Spring中ApplicationContext和beanfactory区别.rar

    在Spring框架中,ApplicationContext和BeanFactory是两种不同的bean容器,它们各自有其特性和应用场景,理解二者的区别对于深入学习和使用Spring至关重要。 首先,BeanFactory是Spring中最基础的bean管理容器,它...

    Spring3.1.3 Ioc在Web容器中的建立

    标题 "Spring3.1.3 Ioc在Web容器中的建立" 涉及的是Spring框架的一个关键特性——依赖注入(Dependency Injection,简称DI),以及如何在Web应用环境中配置和使用它。Spring是Java开发中最流行的轻量级框架之一,...

    加载spring 文件,在web.xml中的配置

    当我们谈论“加载Spring文件,在web.xml中的配置”时,主要是指如何在Web应用启动时初始化Spring IoC(Inversion of Control,控制反转)容器并加载配置文件。 1. **使用ContextLoaderListener** `&lt;listener&gt;`标签...

    在非spring注解类中使用spring容器中的bean_普通类中使用yml配置文件中的配置信息

    虽然通常这个注解用于Spring管理的Bean,但也可以在非Spring管理的类中使用,只要确保配置的加载和绑定过程正确执行。 为了读取YAML配置,你需要在Spring Boot应用的启动类或者其他适当的初始化点,注册`@...

    springBean加载过程源码解析文档,附有代码类名和行数

    Spring Bean 加载过程是 Spring 框架中最核心的部分之一,涉及到 ApplicationContext 的初始化、Bean 的加载和注册等过程。在 Spring Boot 应用程序中,SpringApplication 负责加载和管理 Bean。 SpringApplication...

    三、Spring源码分析——ApplicationContext

    总的来说,ApplicationContext作为Spring的核心组件,扮演着应用程序的“大脑”角色,它负责管理和协调整个Spring容器中的Bean。理解并掌握ApplicationContext的工作原理和使用技巧,对于深度开发和优化Spring应用至...

    在Web项目中集成Spring

    本文将深入探讨如何在Web项目中集成Spring,包括Spring MVC的使用、配置过程以及关键组件的解释。 首先,Spring的核心是IoC(Inversion of Control)容器,它负责管理对象的生命周期和对象间的依赖关系。通过XML...

    web容器中实例化spring相关配置解析

    Web容器中实例化Spring相关配置解析是指在Web容器中实例化Spring容器的相关配置解析。Spring框架是JavaEE应用程序的核心框架之一,它提供了丰富的功能和工具来开发企业级应用程序。为了在Web容器中实例化Spring容器...

    java解决org.springframework.web.context.ContextLoaderListener

    在Java Web开发中,`org.springframework.web.context.ContextLoaderListener` 是Spring框架的一部分,它负责初始化一个Web应用程序的Spring上下文。这个监听器是基于Servlet容器(如Tomcat、Jetty等)的,当Web应用...

    ioc容器在Web容器中的启动.pdf

    总结来说,Spring IOC容器在Web容器中的启动涉及到创建`WebApplicationContext`,加载配置文件中的bean定义,然后通过`refresh()`方法实例化和初始化bean。这个过程确保了Web应用程序能够正确地配置和运行其依赖的...

    spring 获得applicationcontext公用方法

    在Spring框架中,`ApplicationContext`是一个非常重要的接口,它提供了加载和管理Bean定义,以及获取Bean实例的功能。本文将深入探讨如何在Spring中获取`ApplicationContext`的公用方法,并结合提供的两个文件名`...

    Spring动态加载配置文件

    在Spring框架中,动态加载配置文件是一项重要的功能,它使得开发者在开发过程中无需重启应用就能实时更新配置,极大地提高了开发效率。热部署方案是这一功能的具体应用,它允许我们在不中断服务的情况下,对应用程序...

    获取spring容器的方法

    在Web环境中,Spring提供了更便捷的方式来获取`ApplicationContext`,即通过`ServletContext`。这尤其适用于Spring MVC或Spring Boot这样的Web应用。可以通过以下方式获取: ```java import org.springframework....

    Spring和SpringMVC父子容器关系

    ApplicationContext是Spring中最常用的容器,它提供了更高级的功能,如对国际化、事件传播、资源加载等的支持。BeanFactory是Spring的基本容器,负责管理bean的生命周期和依赖注入。 SpringMVC中的...

    web.xml文件中配置(servlet, spring, filter, listenr)的加载顺序

    在`web.xml`中配置Spring时,通常通过Listener来加载Spring容器,这样可以在应用程序启动时初始化所有的Spring Bean。 **示例代码:** ```xml org.springframework.web.context.ContextLoaderListener ...

    利用spring的ApplicationContext在程序中唤醒quartz的job

    在Spring框架中,ApplicationContext是核心组件,它负责加载配置,管理Bean的生命周期,并提供依赖注入。Quartz则是一个强大的任务调度库,可以用于计划和执行周期性任务。本篇文章将探讨如何结合Spring的...

    Spring中ApplicationContext对事件传递

    通过本文的介绍,我们可以了解到在Spring框架中如何通过`ApplicationContext`进行事件的传递。这包括自定义事件的创建、事件监听者的定义以及事件的发布等重要步骤。理解这些机制可以帮助开发者更好地利用Spring的...

Global site tag (gtag.js) - Google Analytics