SpringMVC加载流程( 二 )

该类继承了ContextLoader,并通过contextInitialized方法执行了初始化(传入ServletContext),通过contextDestroyed方法进行资源销毁回收 。重点看ContextLoader方法 。
 ContextLoader在初始化时,会先执行内部的一个静态代码块:
private static final Properties defaultStrategies;static {try {ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, ContextLoader.class);defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);}catch (IOException ex) {throw new IllegalStateException("Could not load 'ContextLoader.properties': " + ex.getMessage());}}这一步会加载classpath下的配置文件ContextLoader.properties,该文件将作为默认配置用于初始化Properties对象defaultStrategies 。
3.1.1. contextInitialized contextInitialized方法的主要内容如下:

SpringMVC加载流程

文章插图
 
过程为:
(1) 判断当前Context是否已经初始化过
 通过判断ServletContext中是否存在key为org.springframework.web.context.ROOT的值
  • 初始化WebApplicationContext:从ContextLoader.properties中查找WebApplicationContext的具体实现,如下:
org.springframework.web.context.WebApplicationContext=org.springframework.web.context.support.XmlWebApplicationContext即XmlWebApplicationContext,然后初始化该类
(2) 配置并刷新该XMLWebApplicationContext
 XMLWebApplicationContext继承简图如下:
SpringMVC加载流程

文章插图
 
层级比较明显,本身也是一个RefreshableConfigApplicationContext(具体内容可以看往期内容) 。其父类保存了ServletContext和ServletConfig两个Web Context相关的对象,其本身也维持了一些默认属性,如
DEFAULT_CONFIG_LOCATION = "/WEB-INF/applicationContext.xml";这个属性就是默认的Spring配置文件的路径 。
 需要指出的是XMLWebApplicationContext重写了父类的loadBeanDefinitions方法
@Overrideprotected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {// Create a new XmlBeanDefinitionReader for the given BeanFactory.XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);// Configure the bean definition reader with this context's// resource loading environment.beanDefinitionReader.setEnvironment(getEnvironment());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);}protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws IOException {String[] configLocations = getConfigLocations();if (configLocations != null) {for (String configLocation : configLocations) {reader.loadBeanDefinitions(configLocation);}}}@Overrideprotected String[] getDefaultConfigLocations() {//Tip:返回配置文件路径if (getNamespace() != null) {return new String[] {DEFAULT_CONFIG_LOCATION_PREFIX + getNamespace() + DEFAULT_CONFIG_LOCATION_SUFFIX};}else {return new String[] {DEFAULT_CONFIG_LOCATION};}}这里用了XmlBeanDefinitionReader来解析Bean定义,且指定了配置文件的加载逻辑,getConfigLocations方法:如果父类的configLocations不为空,则返回该值,否则返回getDefaultConfigLocations的值 。而getDefaultConfigLocations方法逻辑为:如果存在命名空间,则返回/WEB_INF/namespace.xml作为配置文件,否则返回/WEB-INF/applicationContext.xml 。对应上面的demo,将返回配置中的文件(同默认值相同) 。
 XMLWebApplicationContext的初始化步骤为:
  • 读取contextId配置,进行设置
  • 读取contextConfigLocation配置,使用指定的配置文件,若没有则使用上面提到的默认配置文件DEFAULTCONFIGLOCATION
  • 加载contextInitializerClasses指定的class,用于在context刷新前执行自定义处理
  • 调用XMLWebApplicationContext的refresh方法
(3)标记已经初始化
 通过将该根Context存在ServletContext中,并设置值为org.springframework.web.context.ROOT,用于第(1)步的判断
3.1.2. contextDestroyed 销毁过程比较简单,首先调用WebApplicationContext的close方法销毁该Context,然后移除ServletContex中的org.springframework.web.context.ROOT属性值,最后清除ServletContext中所有org.springframework.开头的属性值 。
3.2. DispatcherServlet的加载 同ContextLoaderListener类似,DispatcherServlet依赖于Servlet进行扩展 。DispatcherServlet的结构如下:


推荐阅读