GenericServlet#init(ServletConfig)
中,而后调用this#init()
方法,此处的this指向是DispatcherServlet
对象public void init(ServletConfig config) throws ServletException { this.config = config; this.init(); }
DispatcherServlet
对象执行init()
方法,DispatcherServlet
对象中的这个方法是继承自HttpServletBean
,此时会进入到HttpServletBean#init
中,这里面的重点是initServletBean()
方法,调用对应的子类进行初始化public final void init() throws ServletException { // Set bean properties from init parameters. PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties); if (!pvs.isEmpty()) { try { BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this); ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext()); bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment())); initBeanWrapper(bw); bw.setPropertyValues(pvs, true); } //...忽略 } // Let subclasses do whatever initialization they like. 让子类进行对应的初始化 initServletBean(); }
FrameworkServlet#initServletBean
中,核心是initWebApplicationContext
和initFrameworkServlet
方法protected final void initServletBean() throws ServletException { getServletContext().log("Initializing Spring " + getClass().getSimpleName() + " '" + getServletName() + "'"); try { // this.webApplicationContext = initWebApplicationContext(); // initFrameworkServlet(); } catch (ServletException | RuntimeException ex) { logger.error("Context initialization failed", ex); throw ex; } //log.. }
initWebApplicationContext
方法,对web项目上下文进行初始化protected WebApplicationContext initWebApplicationContext() { //首先得到父容器 WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(getServletContext()); //什么子容器 WebApplicationContext wac = null; //创建父子容器关系 if (this.webApplicationContext != null) { // A context instance was injected at construction time -> use it wac = this.webApplicationContext; if (wac instanceof ConfigurableWebApplicationContext) { ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac; if (!cwac.isActive()) { // The context has not yet been refreshed -> provide services such as // setting the parent context, setting the application context id, etc if (cwac.getParent() == null) { // The context instance was injected without an explicit parent -> set // the root application context (if any; may be null) as the parent cwac.setParent(rootContext); } configureAndRefreshWebApplicationContext(cwac); } } } //查找web容器的引用是否存在, 并建立好空ioc容器 if (wac == null) { // No context instance was injected at construction time -> see if one // has been registered in the servlet context. If one exists, it is assumed // that the parent context (if any) has already been set and that the // user has performed any initialization such as setting the context id wac = findWebApplicationContext(); } //给建好的IOC容器赋值 if (wac == null) { // No context instance is defined for this servlet -> create a local one wac = createWebApplicationContext(rootContext); } //触发刷新方法 if (!this.refreshEventReceived) { // Either the context is not a ConfigurableApplicationContext with refresh // support or the context injected at construction time had already been // refreshed -> trigger initial onRefresh manually here. synchronized (this.onRefreshMonitor) { onRefresh(wac); } } if (this.publishContext) { // Publish the context as a servlet context attribute. String attrName = getServletContextAttributeName(); getServletContext().setAttribute(attrName, wac); } return wac; }
DispatcherServlet
的onRefresh
,在onRefresh
中又调用了initStrategies
方法,初始化SpringMVC的九大组件@Override protected void onRefresh(ApplicationContext context) { initStrategies(context); } /** * Initialize the strategy objects that this servlet uses. * <p>May be overridden in subclasses in order to initialize further strategy objects. */ protected void initStrategies(ApplicationContext context) { //多文件上传组件 initMultipartResolver(context); //本地语言环境 initLocaleResolver(context); //模板处理器 initThemeResolver(context); //HandlerMapping initHandlerMappings(context); //适配器 initHandlerAdapters(context); //异常拦截器 initHandlerExceptionResolvers(context); //视图预处理器 initRequestToViewNameTranslator(context); //视图转换器 initViewResolvers(context); //FlashMap initFlashMapManager(context); }
HandlerMapping
根据request找到相应的处理器。由于Handler(Controller)有两种形式,一种是基于类的Handler,另外一种是基于Method的Handler(也就是咱们经常使用的)css
HandlerAdapter
调用Handler的适配器。若是把Handler(Controller)当作工具的话,那么HandlerAdapter就至关于干活的工人java
HandlerExceptionResolver
对异常的处理web
ViewResolver
用来将String类型的视图名和Locale解析为View类型的视图app
RequestToViewNameTranslator
有的Handler(Controller)处理完后没有设置返回类型,好比是void方法,这是就须要从request中获取viewNameide
LocaleResolver
从request中解析出Locale。Locale表示一个区域,好比zh-cn,对不一样的区域的用户,显示不一样的结果,这就是i18n(SpringMVC中有具体的拦截器LocaleChangeInterceptor)工具
ThemeResolver
主题解析,这种相似于咱们手机更换主题,不一样的UI,css等ui
MultipartResolver
处理上传请求,将普通的request封装成MultipartHttpServletRequestthis
FlashMapManager
用于管理FlashMap,FlashMap用于在redirect重定向中传递参数spa