DispatcherServlet 的创建过程
【参考文章】:SpringMvc 启动原理源码分析
【参考文章】:【Spring】DispatcherServlet的启动和初始化
【参考文章】:servlet 百度百科
1. servlet 生命周期
一个客户端的请求到达 Server;
Server 创建一个请求对象,处理客户端请求;
Server 创建一个响应对象,响应客户端请求;
Server 加载 Servlet 并调用其 init() 进行初始化;
Server 激活 Servlet 的 service() 方法,传递请求和响应对象作为参数;
service() 方法获得关于请求对象的信息,处理请求,访问其他资源,获得需要的信息;
service() 方法使用响应对象的方法,将响应传回Server,最终到达客户端;
一般 Servlet 只初始化一次(只有一个对象),当 Server 不再需要 Servlet 时(一般当 Server 关闭时),Server 调用 Servlet 的 destroy() 方法。
Servlet 容器处理由多个线程产生的多个请求,每个线程执行一个单一的 Servlet 实例的 service() 方法;
Spring MVC 中由一个单例的 DispatcherServlet 处理所有请求。
2. DispatcherServlet 的创建
2.1 构造方法
先调用父类 FrameworkServlet 的构造方法,再调用自己的构造方法;
public class DispatcherServlet extends FrameworkServlet { public DispatcherServlet() { super(); setDispatchOptionsRequest(true); } } public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware { public FrameworkServlet() { } }
2.2 init()
DispatcherServlet 调用基类 HttpServletBean 的 init(),
主要获取 servletContext ,servletConfig 对象
@Override public final void init() throws ServletException { if (logger.isDebugEnabled()) { logger.debug("Initializing servlet '" + getServletName() + "'"); } // Set bean properties from init parameters. try { // 获取servletConfig PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties); // 将dispatcherServlet对象封装到BeanWrapper类里 BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this); // 获取servletContext ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext()); bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment())); // 空的方法 initBeanWrapper(bw); 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. //这个方法由FrameworkServlet提供实现 initServletBean(); if (logger.isDebugEnabled()) { logger.debug("Servlet '" + getServletName() + "' configured successfully"); } }
HttpServletBean 的 init() 又会调用 FrameworkServlet 的 initServletBean();
主要初始化 Spring 的 webApplicationContext 对象
@Override protected final void initServletBean() throws ServletException { getServletContext().log("Initializing Spring " + getClass().getSimpleName() + " '" + getServletName() + "'"); if (logger.isInfoEnabled()) { logger.info("Initializing Servlet '" + getServletName() + "'"); } long startTime = System.currentTimeMillis(); try { // 真正有效的方法 this.webApplicationContext = initWebApplicationContext(); initFrameworkServlet(); } catch (ServletException | RuntimeException ex) { logger.error("Context initialization failed", ex); throw ex; } if (logger.isDebugEnabled()) { String value = this.enableLoggingRequestDetails ? "shown which may lead to unsafe logging of potentially sensitive data" : "masked to prevent unsafe logging of potentially sensitive data"; logger.debug("enableLoggingRequestDetails='" + this.enableLoggingRequestDetails + "': request parameters and headers will be " + value); } if (logger.isInfoEnabled()) { logger.info("Completed initialization in " + (System.currentTimeMillis() - startTime) + " ms"); } }
初始化 WebApplicationContext后,调用 DispatcherServlet中 的 onRefresh();
protected WebApplicationContext initWebApplicationContext() { WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(getServletContext()); WebApplicationContext wac = null; if (this.webApplicationContext != null) { wac = this.webApplicationContext; if (wac instanceof ConfigurableWebApplicationContext) { ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac; if (!cwac.isActive()) { if (cwac.getParent() == null) { cwac.setParent(rootContext); } configureAndRefreshWebApplicationContext(cwac); } } } if (wac == null) { wac = findWebApplicationContext(); } if (wac == null) { wac = createWebApplicationContext(rootContext); } if (!this.refreshEventReceived) { synchronized (this.onRefreshMonitor) { // 初始化 Spring MVC 的基本组件 onRefresh(wac); } } if (this.publishContext) { String attrName = getServletContextAttributeName(); getServletContext().setAttribute(attrName, wac); } return wac; }
onRefresh() 直接调用 initStrategies() ;
@Override protected void onRefresh(ApplicationContext context) { initStrategies(context); }
initStrategies() 初始化基本组件,启动整个 Spring MVC 框架
protected void initStrategies(ApplicationContext context) { //初始化上传文件解析器 initMultipartResolver(context); //初始化本地解析器 initLocaleResolver(context); //主题处理器 initThemeResolver(context); //映射处理器 initHandlerMappings(context); //处理适配器 initHandlerAdapters(context); //异常处理器 initHandlerExceptionResolvers(context); //请求到视图名的翻译器 initRequestToViewNameTranslator(context); //视图解析器 initViewResolvers(context); //初始化FlashManager initFlashMapManager(context); }