第一节 启动过程
1、Servlet 生命周期回顾
2、初始化操作调用路线图
3、创建 IOC 容器对象并存入应用域
4、IOC容器创建
5、获取SpringMVC配置文件名称
5、获取@RequestMapping和视图解析器
6、小结
第一节 启动过程
1、Servlet 生命周期回顾
生命周期环节 | 调用的方法 | 时机 | 次数 |
---|---|---|---|
创建对象 | 无参构造器 | 默认:第一次请求 修改:Web应用启动时 |
一次 |
初始化 | init(ServletConfig servletConfig) | 创建对象后 | 一次 |
处理请求 | service(ServletRequest servletRequest, ServletResponse servletResponse) |
接收到请求后 | 多次 |
清理操作 | destroy() | Web应用卸载之前 | 一次 |
2、初始化操作调用路线图
3、创建 IOC 容器对象并存入应用域
所在类:org.springframework.web.servlet.FrameworkServlet
protected WebApplicationContext initWebApplicationContext() {
WebApplicationContext rootContext =
WebApplicationContextUtils.getWebApplicationContext(getServletContext());
WebApplicationContext wac = null;
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 /> }
if (!this.refreshEventReceived) {<br /> synchronized (this.onRefreshMonitor) {<br /> onRefresh(wac);<br /> }<br /> }
if (this.publishContext) {<br /> // 获取存入应用域时专用的属性名<br /> String attrName = getServletContextAttributeName();
// 存入<br /> getServletContext().setAttribute(attrName, wac);<br /> }
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”);
}
// 通过反射创建 IOC 容器对象<br /> ConfigurableWebApplicationContext wac =<br /> (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
wac.setEnvironment(getEnvironment());
// 设置父容器<br /> wac.setParent(parent);<br /> String configLocation = getContextConfigLocation();<br /> if (configLocation != null) {<br /> wac.setConfigLocation(configLocation);<br /> }<br /> configureAndRefreshWebApplicationContext(wac);
return wac;<br />}<br />注意:创建DispatcherServlet中创建IoC容器时会去应用域中查询已经存在的IoC容器,并作为父容器。如果不存在,父容器就是null,表示没有父容器。这个操作并不多余,下节讲解ContextLoaderListener后就会明白原由。
5、获取SpringMVC配置文件名称
./images
./images
5、获取@RequestMapping和视图解析器
FrameworkServlet.createWebApplicationContext()→configureAndRefreshWebApplicationContext()→wac.refresh()→触发刷新事件→org.springframework.web.servlet.DispatcherServlet.initStrategies()→org.springframework.web.servlet.DispatcherServlet.initHandlerMappings()
6、小结
整个启动过程我们关心如下要点:
- DispatcherServlet 本质上是一个 Servlet,所以天然的遵循 Servlet 的生命周期。所以宏观上是 Servlet 生命周期来进行调度。
- DispatcherServlet 的父类是 FrameworkServlet。
- FrameworkServlet 负责框架本身相关的创建和初始化。
- DispatcherServlet 负责请求处理相关的初始化。
- FrameworkServlet 创建 IOC 容器对象之后会存入应用域。
- FrameworkServlet 完成初始化会调用 IOC 容器的刷新方法。
- 刷新方法完成触发刷新事件,在刷新事件的响应函数中,调用 DispatcherServlet 的初始化方法。
- 在 DispatcherServlet 的初始化方法中初始化了请求映射等。