DispatcherServlet的初始化,是在org.springframework.web.context.ContextLoaderListener完成加载后,才开始的。这时候WebApplicationContext(包含DAO,Service等)已经初始完毕。
DispatcherServlet的初始过程主要完成
1.WebApplicationContext父子容器维护
2.初始化Servlet策略
本文主要内容
- DispatcherServlet的集成体系
- DispatcherServlet初始化过程
1.DispatcherServlet的继承体系
DispatcherServlet是个普通servlet,是访问入口。明白了继承体系,方便梳理初始化模板。
2.DispatcherServlet初始化过程
2.1 init
public final void init() throws ServletException { // Set bean properties from init parameters. //将Servlet配置的参数封装到pvs变量中 try { PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties); BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this); ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext()); bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader)); initBeanWrapper(bw);//bw就是DispatcherServlet bw.setPropertyValues(pvs, true); } // 让子类实现 initServletBean(); if (logger.isDebugEnabled()) { logger.debug("Servlet ‘" + getServletName() + "‘ configured successfully"); } }
2.2 initServletBean方法
protected final void initServletBean() throws ServletException { this.webApplicationContext = initWebApplicationContext(); initFrameworkServlet();//子类可以实现 }
初始化webApplicationContext ;初始化FrameworkServlet
2.3 initWebApplicationContext方法
protected WebApplicationContext initWebApplicationContext() { WebApplicationContext wac = findWebApplicationContext(); if (wac == null) { // No fixed context defined for this servlet - create a local one. WebApplicationContext parent = WebApplicationContextUtils.getWebApplicationContext(getServletContext()); wac = createWebApplicationContext(parent); } if (!this.refreshEventReceived) { // Apparently not a ConfigurableApplicationContext with refresh support: // triggering initial onRefresh manually here. onRefresh(wac);////调用DispatcherServlet.initStrategies入口 } if (this.publishContext) { // Publish the context as a servlet context attribute. String attrName = getServletContextAttributeName(); getServletContext().setAttribute(attrName, wac); ... } } return wac; } protected WebApplicationContext createWebApplicationContext(ApplicationContext parent) { Class<?> contextClass = getContextClass(); ConfigurableWebApplicationContext wac = (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass); wac.setParent(parent);//维护双亲委派 wac.setServletContext(getServletContext()); wac.setServletConfig(getServletConfig()); wac.setNamespace(getNamespace()); wac.setConfigLocation(getContextConfigLocation()); //调用DispatcherServlet.initStrategies入口 wac.addApplicationListener(new SourceFilteringListener(wac, new ContextRefreshListener())); postProcessWebApplicationContext(wac); wac.refresh(); return wac; } private class ContextRefreshListener implements ApplicationListener<ContextRefreshedEvent> { public void onApplicationEvent(ContextRefreshedEvent event) { FrameworkServlet.this.onApplicationEvent(event); } }
2.5.initStrategies方法
protected void initStrategies(ApplicationContext context) { initMultipartResolver(context); initLocaleResolver(context); initThemeResolver(context); initHandlerMappings(context); initHandlerAdapters(context); initHandlerExceptionResolvers(context); initRequestToViewNameTranslator(context); initViewResolvers(context); }
初始化9个组件。
初始化组件过程,大体都是先从容器中获取,获取不到,则调用getDefaultStrategy(ApplicationContext context, Class<T> strategyInterface)方法。
默认配置来自DispatcherServlet.properties
org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping, org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter, org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter, org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver, org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver, org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver
2.6.initHandlerMappings方法
private void initHandlerMappings(ApplicationContext context) { this.handlerMappings = null; if (this.detectAllHandlerMappings) { // Find all HandlerMappings in the ApplicationContext, including ancestor contexts. Map<String, HandlerMapping> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false); if (!matchingBeans.isEmpty()) { this.handlerMappings = new ArrayList<HandlerMapping>(matchingBeans.values()); // We keep HandlerMappings in sorted order. OrderComparator.sort(this.handlerMappings); } } else { ... } } }
将spring mvc容器中HandlerMapping对象赋给handlerMappings 列表。这些对象都是在标签解析时,自动加载入容器中的。具体<SpringMVC源码分析(1)标签解析>
2.7 initHandlerAdapters方法
与initHandlerMappings思路完全一致。