ServletContext
ServletContext 是 WEB 利用的全局的贮存信息的空间,服务器启动就创立,服务器敞开则销毁,即利用上下文
Spring 容器的初始化
WEB 利用启动时,ServletContext 初始化,Spring 提供的 ContextLoaderListener 会监听到这个事件,ContextLoaderListener.contextInitialized 办法会被调用
// 在这个办法中,Spring 会初始化根上下文,即 WebApplicationContext
initWebApplicationContext(event.getServletContext())
WebApplicationContext 理论的实现类是 XmlWebApplicationContext,这个就是 Spring 的 IOC 容器,对应治理的 Bean 的定义由 web.xml 中的 context-param 标签指定(即 applicationContext.xml)
在这个 IOC 容器初始化结束后,Spring 以 WebApplicationContext.ROOTWEBAPPLICATIONCONTEXTATTRIBUTE 为属性 Key,将其存储到 ServletContext 中,便于获取
SpringMVC 的启动过程
web.xml 中的配置
<servlet>
<servlet-name>service_dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/services/service_dispatcher-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
这段配置会初始化 DispatcherServlet,load-on-startup 示意启动容器时初始化该 Servlet
- SpringMVC 启动的过程,实际上是 DispatcherServlet 的初始化过程
DispatcherServlet 继承关系为 FrameworkServlet -> HttpServletBean -> HttpServlet -> Servlet,通过应用 Servlet API 来对 HTTP 申请进行响应,成为 SpringMVC 的前端处理器,用以转发、匹配、解决每个申请。
- DispatcherServlet 初始化从 HttpServletBean 笼罩父类的 init 办法开始
public final void init() throws ServletException {if (logger.isDebugEnabled()) {logger.debug("Initializing servlet'" + getServletName() + "'");
}
// Set bean properties from init parameters.
try {
// 取得 web.xml 中的 contextConfigLocation 配置属性(即 springmvc-config.xml),Spring MVC 的配置文件
PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
// 获取 ServletContext
ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());
bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment()));
// 模板办法,能够在子类中调用,做一些初始化工作,bw 代表 DispatcherServelt
initBeanWrapper(bw);
// 将配置的初始化值设置到 DispatcherServlet 中
bw.setPropertyValues(pvs, true);
}
catch (BeansException ex) {logger.error("Failed to set bean properties on servlet'" + getServletName() + "'", ex);
throw ex;
}
// Let subclasses do whatever initialization they like.
// 模板办法,子类初始化的入口办法
initServletBean();
if (logger.isDebugEnabled()) {logger.debug("Servlet'" + getServletName() + "'configured successfully");
}
}
HttpServletBean 中通过 Spring 的委托类 BeanWrapper 来对 DispatcherServlet 设值,并在 FrameworkServlet.initServletBean() 中进一步初始化上下文
FrameworkServlet 利用 WebApplicationContext.ROOTWEBAPPLICATIONCONTEXTATTRIBUTE 从 ServletContext 中获取 Spring 的根上下文(即 WebApplicationContext)作为父上下文
DispatcherServlet 取得了父上下文之后,在其 initStrategies 初始化处理器映射、视图解析等。初始化结束后,Spring 以与 Servlet 的名字相干(此处不是简略的以 Servlet 名为 Key,而是通过一些转换)的属性为属性 Key,也将其存到 ServletContext 中,以便后续应用
- 故,在 applicationContext.xml 中将 @Controller 正文的组件排除在外,而在 dispatcherServlet 加载的配置文件中将 @Controller 正文的组件加载进来,不便 DispatcherServlet 进行管制和查找