1.根据我们常用的web.xml里,我们找到的org.springframework.web.context.ContextLoaderListener。web.xml如下
<?xml version="1.0" encoding="UTF-8"?>
<web-app
version="3.0"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<display-name>moon</display-name>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath*:applicationContext.xml
</param-value>
</context-param>
</web-app>
- 其实ContextLoaderListener是一个ServletContextListener,一个web容器的监听器。根据其父类org.springframework.web.context.ContextLoader初始化的策略配置,找到类目录下面的ContextLoader.properties文件。里面配置着一个Spring上下文类。
# 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.
org.springframework.web.context.WebApplicationContext=org.springframework.web.context.support.XmlWebApplicationContext
额外知识点:
参考《ClassPathResource知识点》
- 加载策略资源(ContextLoader.properties)后,web容器启动时会调用ContextLoaderListener的contextInitialized方法。
- contextInitialized方法里初始化ContextLoader.properties配置的org.springframework.web.context.support.XmlWebApplicationContext,这个初始化过程有点长。
4.1 从ServletContext获取对象springcontext对象,如果存在则抛异常。key=org.springframework.web.context.WebApplicationContext.ROOT
4.2 从ContextLoader.properties获取className=org.springframework.web.context.support.XmlWebApplicationContext
4.3 通过ClassUtils工具实例化spring的ApplicationContext,我们能够看出他是使用ContextLoader类的类加载器,这里有个可以弄个知识点《ClassUtils知识点》
ClassUtils.forName(contextClassName, ContextLoader.class.getClassLoader())
4.4 XmlWebApplicationContext实例化时,其一些列父类也将初始化和实例化(我稍微地简化说,具体的可以看源码):
层次 | 类名 | 作用 |
---|---|---|
第0层 | org.springframework.web.context.support.XmlWebApplicationContext | 定义默认配置文件,如/WEB-INF/applicationContext.xml |
第1层 | org.springframework.web.context.support.AbstractRefreshableWebApplicationContext | 声明了ServletContext servletContext和ServletConfig servletConfig |
第2层 | org.springframework.context.support.AbstractRefreshableConfigApplicationContext | 此时就跟web没多大关系了,定义了配置变量String[] configLocations |
第3层 | org.springframework.context.support.AbstractRefreshableApplicationContext | 此层就重要了,定义了DefaultListableBeanFactory beanFactory |
第4层 | org.springframework.context.support.AbstractApplicationContext | 此层定义了父context,还有ApplicationContext的其他配置等,refresh()方法 |
第5层 | org.springframework.core.io.DefaultResourceLoader | 此层与ApplicationContext没多大关系,从包名也能看出,声明了ClassLoader |
第6层(最后一层) | org.springframework.core.io.ResourceLoader | spring的作者的注释是Strategy interface for loading resources,嗯哈,大概猜是使用策略模式的接口 |
-
实例化完XmlWebApplicationContext类后,就开始做点事情了。在ContextLoader里,有个方法configureAndRefreshWebApplicationContext(cwac, servletContext),从方法名就能看出是配置和刷新ApplicationContext。
5.1 设置ServletContext,参考第1层
5.2 设置configLocations,参考第2层,这里又一个知识点《StringUtils知识点》
5.3 调用AbstractRefreshableWebApplicationContext的createEnvironment()方法来初始化StandardServletEnvironment对象。参考知识点《StandardServletEnvironment知识点》
5.4 调用StandardServletEnvironment对象initPropertySources(ServletContext servletContext, ServletConfig servletConfig)方法来获取web容器所有配置信息。配置信息都在放在StandardServletEnvironment对象的MutablePropertySources对象里。
5.5 customizeContext(sc, wac)自定义初始化applicationContext的一些信息,里面是获取实现org.springframework.context.ApplicationContextInitializer接口的一些方法调用。一个知识点也诞生《ApplicationContextInitializer知识点》5.6 重头戏来了,refresh ApplicationContext!!!,调用第4层的refresh()方法。
5.6.1 第一步:加载ServletContext和ServletConfig参数,并使用PropertySourcesPropertyResolver校验是否有必须的配置缺失,可参考知识点《PropertySourcesPropertyResolver知识点》。 5.6.2 第二步:实例化BeanFactory,交给子类AbstractRefreshableApplicationContext来实例化(参考第3层),实例化了org.springframework.beans.factory.support.DefaultListableBeanFactory对象作为变量beanFactory的值。并配置是否允许覆盖bean和是否允许循环引用,默认都是否。 5.6.3 第三步:第3层AbstractRefreshableApplicationContext去loadBeanDefinitions,loadBeanDefinitions方法被子类XmlWebApplicationContext覆写了,创建org.springframework.beans.factory.xml.XmlBeanDefinitionReader对象进行加载Bean的定义。这个是重点核心的知识点,参考《XmlBeanDefinitionReader知识点》。 看到这里应该知道每一层ApplicationContext的作用吧,一层一层往上递进 5.6.4 第四步: //TODO 正在研读XmlBeanDefinitionReader
- //TODO
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。