前言
spring框架作为目前主流的j2ee框架,作为开发者不仅要会使用,更应该学习框架的内部原理,理解其设计思想,以便更好地使用框架,提升自己的能力。
从web.xml开始
spring web项目往往需要一个web.xml
的配置文件,该文件就是tomcat加载启动spring容器的入口.
web.xml
<display-name>Archetype Created Web Application</display-name>
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>stat-controller.root</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:application-context.xml</param-value>
</context-param>
<!--ApplicationContext 监听器, 初始化根上下文, ContextLoaderListener监听器是spring容器启动初始化的入口 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
下面来看看spring容器启动过程的时序图
ContextLoaderListener
实现了ServletContextListener
接口
public interface ServletContextListener extends EventListener {
//web容器启动接口,根据ServletContextEvent上下文
public void contextInitialized(ServletContextEvent sce);
//销毁web容器
public void contextDestroyed(ServletContextEvent sce);
}
tomcat在启动后,会notify
监听器ServletContextListener
执行contextInitialized(ServletContextEvent event)
方法来进行spring容器的初始化工作.contextInitialized
会创建ContextLoader
并调用其initWebApplicationContext
来执行初始化。
/**
* Initialize Spring's web application context for the given servlet context
*/
public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
·····
long startTime = System.currentTimeMillis();
try {
// 创建WebApplicationContext
if (this.context == null) {
this.context = createWebApplicationContext(servletContext);
}
if (this.context instanceof ConfigurableWebApplicationContext) {
//如果是基于配置的applicationContext,执行此分支
ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;
if (!cwac.isActive()) {
if (cwac.getParent() == null) {
ApplicationContext parent = loadParentContext(servletContext);
cwac.setParent(parent);
}
// 对cwac属性进行完善并且调用refresh启动ioc容器
configureAndRefreshWebApplicationContext(cwac, servletContext);
}
}
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
···········
return this.context;
}
}
在configureAndRefreshWebApplicationContext
方法中,完成了对配置文件的定位,以及系统环境配置的初始化.
protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {
···········
//设置上下文,以及配置文件的位置
wac.setServletContext(sc);
String configLocationParam = sc.getInitParameter(CONFIG_LOCATION_PARAM);
if (configLocationParam != null) {
wac.setConfigLocation(configLocationParam);
}
// 设置系统环境配置
ConfigurableEnvironment env = wac.getEnvironment();
if (env instanceof ConfigurableWebEnvironment) {
((ConfigurableWebEnvironment) env).initPropertySources(sc, null);
}
customizeContext(sc, wac);
// 进行ioc容器的启动
wac.refresh();
}
最终wac.refresh()会开始ioc
容器的初始化.