SpringMVC源码解析之Servlet
SpringMVC源码解析之GenericServlet和HttpServlet
一、DispatcherServlet类
DispatcherServlet是SpringMVC的基础Servlet,基于Java-bean提供的应用上下文(application context)的集成。
Dispatcher主要提供了以下功能:
(1)通过Servlet提供了对WebApplicationContext实例的管理。Servlet的配置由Servlet命名空间内的beans确定。
(2)在处理请求时提供了事件机制,无论是否成功都会发布事件。
二、DispatcherServlet初始化
在上篇博客中已经提到,HttpServlet将初始化的逻辑委托给了无参init方法处理,下面我们从无参的init方法开始了解DispatcherServlet的初始化过程。
1. HttpServletBean#init()
public final void init() throws ServletException {
if (logger.isDebugEnabled()) {
logger.debug("Initializing servlet '" + getServletName() + "'");
}
//配置的参数封装到pvs
// Set bean properties from init parameters.
PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);
if (!pvs.isEmpty()) {
try {
//Spring中bean的包装工具类,用于直接修改bean对象的属性值
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());
bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment()));
//空的模板方法,留给子类重写
initBeanWrapper(bw);
//根据配置的参数值修改Servlet属性
bw.setPropertyValues(pvs, true);
}
catch (BeansException ex) {
if (logger.isErrorEnabled()) {
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");
}
}
2. FrameworkServlet#initServletBean()
FrameServlet对initServletBean方法进行了重写。
protected final void initServletBean() throws ServletException {
getServletContext().log("Initializing Spring FrameworkServlet '" + getServletName() + "'");
if (this.logger.isInfoEnabled()) {
this.logger.info("FrameworkServlet '" + getServletName() + "': initialization started");
}
long startTime = System.currentTimeMillis();
try {
//初始化成员变量webApplicationContext
this.webApplicationContext = initWebApplicationContext();
//默认空的模板方法
initFrameworkServlet();
}
catch (ServletException ex) {
this.logger.error("Context initialization failed", ex);
throw ex;
}
catch (RuntimeException ex) {
this.logger.error("Context initialization failed", ex);
throw ex;
}
if (this.logger.isInfoEnabled()) {
long elapsedTime = System.currentTimeMillis() - startTime;
this.logger.info("FrameworkServlet '" + getServletName() + "': initialization