第一节 启动过程
1、Servlet 生命周期回顾
2、初始化操作调用路线图
3、创建 IOC 容器对象并存入应用域
4、IOC容器创建
5、获取SpringMVC配置文件名称
5、获取@RequestMapping和视图解析器
6、小结

第一节 启动过程

1、Servlet 生命周期回顾

03 启动过程 - 图1

生命周期环节 调用的方法 时机 次数
创建对象 无参构造器 默认:第一次请求
修改:Web应用启动时
一次
初始化 init(ServletConfig servletConfig) 创建对象后 一次
处理请求 service(ServletRequest servletRequest,
ServletResponse servletResponse)
接收到请求后 多次
清理操作 destroy() Web应用卸载之前 一次

2、初始化操作调用路线图

03 启动过程 - 图2

3、创建 IOC 容器对象并存入应用域

所在类:org.springframework.web.servlet.FrameworkServlet
protected WebApplicationContext initWebApplicationContext() {
WebApplicationContext rootContext =
WebApplicationContextUtils.getWebApplicationContext(getServletContext());
WebApplicationContext wac = null;

  1. if (this.webApplicationContext != null) {<br /> wac = this.webApplicationContext;<br /> if (wac instanceof ConfigurableWebApplicationContext) {<br /> ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;<br /> if (!cwac.isActive()) {<br /> if (cwac.getParent() == null) {<br /> cwac.setParent(rootContext);<br /> }<br /> configureAndRefreshWebApplicationContext(cwac);<br /> }<br /> }<br /> }<br /> if (wac == null) {<br /> wac = findWebApplicationContext();<br /> }<br /> if (wac == null) {<br /> // 创建 IOC 容器<br /> wac = createWebApplicationContext(rootContext);<br /> }
  2. if (!this.refreshEventReceived) {<br /> synchronized (this.onRefreshMonitor) {<br /> onRefresh(wac);<br /> }<br /> }
  3. if (this.publishContext) {<br /> // 获取存入应用域时专用的属性名<br /> String attrName = getServletContextAttributeName();
  4. // 存入<br /> getServletContext().setAttribute(attrName, wac);<br /> }
  5. return wac;<br />}<br />看到这一点的意义:SpringMVC 有一个工具方法,可以从应用域获取 IOC 容器对象的引用。

工具类:org.springframework.web.context.support.WebApplicationContextUtils
工具方法:getWebApplicationContext()
@Nullable
public static WebApplicationContext getWebApplicationContext(ServletContext sc) {
return getWebApplicationContext(sc, WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
}

4、IOC容器创建

所在类:org.springframework.web.servlet.FrameworkServlet
protected WebApplicationContext createWebApplicationContext(@Nullable ApplicationContext parent) {
Class<?> contextClass = getContextClass();
if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {
throw new ApplicationContextException(
“Fatal initialization error in servlet with name ‘“ + getServletName() +
“‘: custom WebApplicationContext class [“ + contextClass.getName() +
“] is not of type ConfigurableWebApplicationContext”);
}

  1. // 通过反射创建 IOC 容器对象<br /> ConfigurableWebApplicationContext wac =<br /> (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
  2. wac.setEnvironment(getEnvironment());
  3. // 设置父容器<br /> wac.setParent(parent);<br /> String configLocation = getContextConfigLocation();<br /> if (configLocation != null) {<br /> wac.setConfigLocation(configLocation);<br /> }<br /> configureAndRefreshWebApplicationContext(wac);
  4. return wac;<br />}<br />注意:创建DispatcherServlet中创建IoC容器时会去应用域中查询已经存在的IoC容器,并作为父容器。如果不存在,父容器就是null,表示没有父容器。这个操作并不多余,下节讲解ContextLoaderListener后就会明白原由。

5、获取SpringMVC配置文件名称

03 启动过程 - 图3
./images
03 启动过程 - 图4
./images

5、获取@RequestMapping和视图解析器

FrameworkServlet.createWebApplicationContext()→configureAndRefreshWebApplicationContext()→wac.refresh()→触发刷新事件→org.springframework.web.servlet.DispatcherServlet.initStrategies()→org.springframework.web.servlet.DispatcherServlet.initHandlerMappings()
03 启动过程 - 图5

03 启动过程 - 图6

6、小结

整个启动过程我们关心如下要点:

  • DispatcherServlet 本质上是一个 Servlet,所以天然的遵循 Servlet 的生命周期。所以宏观上是 Servlet 生命周期来进行调度。
  • DispatcherServlet 的父类是 FrameworkServlet。
    • FrameworkServlet 负责框架本身相关的创建和初始化。
    • DispatcherServlet 负责请求处理相关的初始化。
  • FrameworkServlet 创建 IOC 容器对象之后会存入应用域。
  • FrameworkServlet 完成初始化会调用 IOC 容器的刷新方法。
  • 刷新方法完成触发刷新事件,在刷新事件的响应函数中,调用 DispatcherServlet 的初始化方法。
  • 在 DispatcherServlet 的初始化方法中初始化了请求映射等。

回目录 下一节