web应用的启动过程
熟悉的web应用都带有一个web.xml配置文件,web应用的启动就是从这个web.xml开始的。web应用放入servlet容器如tomcat中,tomcat启动时加载web.xml。web.xml中有四个常用的配置项:- listener 经常被叫做监听器
- context-param
- filter 经常被叫做过滤器
- servlet servlet将接收到的http请求交给对应的servlet处理
首先创建web.xml中配置的监听器,监听容器中发生的事件。
<listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
然后创建一个servletContext,将context-param中配置的参数放入其中,该servletContext在该应用中所有对象共享。
<context-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/spring-mybatis.xml,/WEB-INF/spring-security.xml,/WEB-INF/spring-redis.xml,/WEB-INF/spring-quartz-cluster.xml,/WEB-INF/application-dictionary.xml,/WEB-INF/application-mail.xml,/WEB-INF/activeMq.xml </param-value> </context-param>
- 这时监听器监听到servletContext的创建事件后,进行对应的初始化操作:
```
void org.springframework.web.context.ContextLoaderListener.contextInitialized(ServletContextEvent event)
/** - Initialize the root web application context.
*/
@Override
public void contextInitialized(ServletContextEvent event) {
initWebApplicationContext(event.getServletContext());
}
``` - 创建过滤器filter
- 创建Servlet并初始化Servlet
- 启动完成,监听服务器端口接收http请求。
SpringFramework的初始化
从启动过程可以看到,springframework利用一个监听器ContextLoaderListener触发初始化。当监听到servletContext创建完成之后,就会进行webApplicationContext的初始化过程,而webApplicationContext初始化完成之后就会把它放入servletContext中,设置为根上下文org.springframework.web.context.WebApplicationContext.root
public WebApplicationContext initWebApplicationContext(ServletContext 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"); if (logger.isInfoEnabled()) { logger.info("Root WebApplicationContext: initialization started"); } long startTime = System.currentTimeMillis(); try { // Store context in local instance variable, to guarantee that // it is available on ServletContext shutdown. if (this.context == null) { this.context = createWebApplicationContext(servletContext);//新建一个WebApplicationContext,实际上就是调用一个WebApplicationContext子类的构造器新建一个对象,如果没有在web.xml中制定contextClass,新建一个org.springframework.web.context.support.XmlWebApplicationContext对象 } 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);//根applicationContext的parent为null } configureAndRefreshWebApplicationContext(cwac, servletContext); } } //把已经初始化的根ApplicationContext作为servletContext的一个属性 servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
rootApplicationContext的初始化过程在configureAndRefreshWebApplicationContext方法中完成。下面看下rootApplicationContext的初始化过程。