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中的配置
service_dispatcher
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
/WEB-INF/spring/services/service_dispatcher-servlet.xml
1
这段配置会初始化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进行控制和查找