SpringMVC源码(三):九大内置组件初始化
在源码(二):MVC容器启动的分析中,MVC容器刷新完成后,通过发布事件及事件监听处理器来初始化MVC的九大组件,下面来分析下这九大组件初始化的细节。
概览
初始化MVC组件,DispatcherServlet#initStrategies 核心代码:
1 // 初始化组件 2 protected void initStrategies(ApplicationContext context) { 3 // 初始化 MultipartResolver:主要用来处理文件上传.如果定义过当前类型的bean对象,那么直接获取,如果没有的话,可以为null 4 initMultipartResolver(context); 5 // 初始化 LocaleResolver:主要用来处理国际化配置,基于URL参数的配置(AcceptHeaderLocaleResolver), 6 // 基于session的配置(SessionLocaleResolver),基于cookie的配置(CookieLocaleResolver) 7 initLocaleResolver(context); 8 // 初始化 ThemeResolver:主要用来设置主题Theme 9 initThemeResolver(context); 10 // 初始化 HandlerMapping:映射器,用来将对应的request跟controller进行对应 11 initHandlerMappings(context); 12 // 初始化 HandlerAdapter:处理适配器,主要包含Http请求处理器适配器,简单控制器处理器适配器,注解方法处理器适配器 13 initHandlerAdapters(context); 14 // 初始化 HandlerExceptionResolver:基于HandlerExceptionResolver接口的异常处理 15 initHandlerExceptionResolvers(context); 16 // 初始化 RequestToViewNameTranslator:当controller处理器方法没有返回一个View对象或逻辑视图名称, 17 // 并且在该方法中没有直接往response的输出流里面写数据的时候,spring将会采用约定好的方式提供一个逻辑视图名称 18 initRequestToViewNameTranslator(context); 19 // 初始化 ViewResolver: 将ModelAndView选择合适的视图进行渲染的处理器 20 initViewResolvers(context); 21 // 初始化 FlashMapManager: 提供请求存储属性,可供其他请求使用 22 initFlashMapManager(context); 23 }
DispatcherServlet中持有SpringMVC内置的九大组件属性。
一、初始化文件上传组件
初始化文件上传组件initMultipartResolver(context),DispatcherServlet#initMultipartResolver核心伪代码:
1 // MultipartResolver对象在MVC容器中的beanName 2 public static final String MULTIPART_RESOLVER_BEAN_NAME = "multipartResolver"; 3 4 // 初始化MultipartResolver 5 private void initMultipartResolver(ApplicationContext context) { 6 try { 7 // 从spring上下文获取名称为 multipartResolver ,类型为MultipartResolver的Bean 8 this.multipartResolver = context.getBean(MULTIPART_RESOLVER_BEAN_NAME, MultipartResolver.class); 9 } 10 // 若未定义bean信息,默认为空 11 catch (NoSuchBeanDefinitionException ex) { 12 this.multipartResolver = null; 13 } 14 }
从容器中获取beanName为multipartResolver,类型为MultipartResolver的bean对象,若未设置该bean,默认为空。
二、初始化参数解析器
初始化参数解析器initLocaleResolver(context),DispatcherServlet#initLocaleResolver核心伪代码:
1 // LocaleResolver对象在MVC容器中的beanName 2 public static final String LOCALE_RESOLVER_BEAN_NAME = "localeResolver"; 3 4 // 初始化参数解析器 5 private void initLocaleResolver(ApplicationContext context) { 6 try { 7 // 从上下文中获取Bean名称为 LocaleResolver的对象 8 this.localeResolver = context.getBean(LOCALE_RESOLVER_BEAN_NAME, LocaleResolver.class); 9 } 10 catch (NoSuchBeanDefinitionException ex) { 11 // 从配置文件中获取默认的AcceptHeaderLocaleResolver对象 12 this.localeResolver = getDefaultStrategy(context, LocaleResolver.class); 13 } 14 }
从容器中获取beanName为localeResolver,类型为LocaleResolver的bean对象,若未设置该bean,获取默认的LocaleResolver,AcceptHeaderLocaleResolver对象。
三、初始化主题资源
1 // ThemeResolver对象在MVC容器中的beanName 2 public static final String THEME_RESOLVER_BEAN_NAME = "themeResolver"; 3 4 // 初始化主题资源对象 5 private void initThemeResolver(ApplicationContext context) { 6 try { 7 // 从上下文中获取Bean名称为 themeResolver的对象 8 this.themeResolver = context.getBean(THEME_RESOLVER_BEAN_NAME, ThemeResolver.class); 9 } 10 catch (NoSuchBeanDefinitionException ex) { 11 // 从配置文件中获取默认的FixedThemeResolver 12 this.themeResolver = getDefaultStrategy(context, ThemeResolver.class); 13 } 14 }
从容器中获取beanName为themeResolver,类型为ThemeResolver的bean对象,若未设置该bean,获取默认的ThemeResolver,FixedThemeResolver对象。
四、初始化HandlerMapping映射器
初始化HandlerMapping映射器initHandlerMappings(context), DispatcherServlet#initHandlerMappings核心伪代码:
1 //HandlerMapping对象在MVC容器中的beanName 2 public static final String HANDLER_MAPPING_BEAN_NAME = "handlerMapping"; 3 4 // 初始化HandlerMapping映射器 5 private void initHandlerMappings(ApplicationContext context) { 6 // 将handlerMappings置空 7 this.handlerMappings = null; 8 9 // 如果开启探测功能,则扫描已注册的HandlerMapping的bean,添加到handlerMappings中 10 if (this.detectAllHandlerMappings) { 11 // 扫描已注册的handlerMapping的bean 12 Map<String, HandlerMapping> matchingBeans = 13 BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false); 14 // 添加到handlerMappings中,并进行排序 15 if (!matchingBeans.isEmpty()) { 16 this.handlerMappings = new ArrayList<>(matchingBeans.values()); 17 AnnotationAwareOrderComparator.sort(this.handlerMappings); 18 } 19 } 20 // 如果关闭探测功能,则获取Bean名称为handlerMapping对应的bean,将其添加到handlerMappings 21 else { 22 HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class); 23 this.handlerMappings = Collections.singletonList(hm); 24 } 25 // 若未配置handlerMapping,获取默认配置的handlerMapping -> BeanNameUrlHandlerMapping、RequestMappingHandlerMapping、RouterFunctionMapping 26 if (this.handlerMappings == null) { 27 // 获取默认的handlerMapping策略 28 this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class); 29 } 30 }
1、判断是否开启了HandlerMapping自动探测功能,若功能开启,获取所有HandlerMapping类型的对象,并添加至handlerMappings集合中,包含DispatcherServlet.properties文件中配置的默认HandlerMapping:BeanNameUrlHandlerMapping、RequestMappingHandlerMapping、RouterFunctionMapping;
2、若关闭了HandlerMapping自动探测功能,获取beanName为handlerMapping,类型为HandlerMapping的对象并添加至handlerMappings集合中;
3、若未配置handlerMappings,获取SpringMVC默认的HandlerMapping实现,BeanNameUrlHandlerMapping、RequestMappingHandlerMapping、RouterFunctionMapping。
注意:在初始化HandlerMapping组件时,会初始化DispatcherServlet中的handlerMappings属性,用于在MVC请求流程中,获取HandlerExecutionChain处理器执行器链。
五、初始化HandlerAdapter处理适配器
初始化处理适配器initHandlerAdapters(context), DispatcherServlet#initHandlerAdapters核心伪代码:
1 // HandlerAdapter对象在MVC容器中的beanName 2 public static final String HANDLER_ADAPTER_BEAN_NAME = "handlerAdapter"; 3 4 // 初始化HandlerAdapters适配处理器 5 private void initHandlerAdapters(ApplicationContext context) { 6 this.handlerAdapters = null; 7 8 // 如果开启探测功能,则扫描已注册的HandlerAdapter的bean,添加到handlerAdapters中 9 if (this.detectAllHandlerAdapters) { 10 // 探测容器中所有的HandlerAdapter适配处理器,包括父类中的 11 Map<String, HandlerAdapter> matchingBeans = 12 BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false); 13 // 容器中存在HandlerAdapter类型的bean 14 if (!matchingBeans.isEmpty()) { 15 // 添加至handlerAdapters集合中 16 this.handlerAdapters = new ArrayList<>(matchingBeans.values()); 17 // 对集合handlerAdapters做排序 18 AnnotationAwareOrderComparator.sort(this.handlerAdapters); 19 } 20 } 21 // 若未开启探测功能 22 else { 23 // 获取容器中beanName为handlerAdapter,类型为HandlerAdapter的bean对象 24 HandlerAdapter ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME, HandlerAdapter.class); 25 // 添加至handlerAdapters集合中 26 this.handlerAdapters = Collections.singletonList(ha); 27 } 28 29 // 如果未获得到,则获得默认配置的HandlerAdapter类,HttpRequestHandlerAdapter,SimpleControllerHandlerAdapter,RequestMappingHandlerAdapter 30 if (this.handlerAdapters == null) { 31 // SimpleControllerHandlerAdapter、RequestMappingHandlerAdapter、HandlerFunctionAdapter 32 this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class); 33 } 34 }
1、判断是否开启了HandlerAdapter自动探测功能,若功能开启,获取所有HandlerAdapter类型的对象,并添加至handlerAdapters集合中;
2、若关闭了HandlerAdapter自动探测功能,获取beanName为handlerAdapter,类型为HandlerAdapter的对象并添加至handlerAdapters集合中;
3、若未配置HandlerAdapter,获取SpringMVC默认的HandlerAdapter实现,SimpleControllerHandlerAdapter、RequestMappingHandlerAdapter、HttpRequestHandlerAdapter。
六、初始化HandlerExceptionResolver异常处理器
初始化处理适配器initHandlerExceptionResolvers(context), DispatcherServlet#initHandlerExceptionResolvers核心伪代码:
1 // HandlerExceptionResolver对象在MVC容器中的beanName 2 public static final String HANDLER_EXCEPTION_RESOLVER_BEAN_NAME = "handlerExceptionResolver"; 3 4 // 初始化异常处理器 5 private void initHandlerExceptionResolvers(ApplicationContext context) { 6 // 置空 handlerExceptionResolver 处理 7 this.handlerExceptionResolvers = null; 8 9 // 自动扫描handlerExceptionResolver类型的bean 10 if (this.detectAllHandlerExceptionResolvers) { 11 // 获取容器中所有HandlerExceptionResolver类型的bean对象 12 Map<String, HandlerExceptionResolver> matchingBeans = BeanFactoryUtils 13 .beansOfTypeIncludingAncestors(context, HandlerExceptionResolver.class, true, false); 14 // 容器中存在HandlerExceptionResolver类型的bean对象 15 if (!matchingBeans.isEmpty()) { 16 // 添加至handlerExceptionResolvers集合中 17 this.handlerExceptionResolvers = new ArrayList<>(matchingBeans.values()); 18 // 排序 19 AnnotationAwareOrderComparator.sort(this.handlerExceptionResolvers); 20 } 21 } 22 // 获取名字为HANDLER_EXCEPTION_RESOLVER_BEAN_NAME的bean 23 else { 24 // 获取容器中beanName为handlerExceptionResolver, 类型为HandlerExceptionResolver的bean对象 25 HandlerExceptionResolver her = 26 context.getBean(HANDLER_EXCEPTION_RESOLVER_BEAN_NAME, HandlerExceptionResolver.class); 27 // 添加至handlerExceptionResolvers集合中 28 this.handlerExceptionResolvers = Collections.singletonList(her); 29 } 30 31 // 如果未获得到 32 if (this.handlerExceptionResolvers == null) { 33 // 获取默认配置的handlerExceptionResolver类,ExceptionHandlerExceptionResolver,ResponseStatusExceptionResolver,DefaultHandlerExceptionResolver 34 this.handlerExceptionResolvers = getDefaultStrategies(context, HandlerExceptionResolver.class); 35 } 36 }
1、判断是否开启了HandlerExceptionResolver自动探测功能,若功能开启,获取所有HandlerExceptionResolver类型的对象,并添加至handlerExceptionResolvers集合中;
2、若关闭了HandlerExceptionResolver自动探测功能,beanName为handlerExceptionResolver, 类型为HandlerExceptionResolver的bean对象并添加至handlerExceptionResolvers集合中;
3、若未配置HandlerExceptionResolver,获取SpringMVC默认的HandlerExceptionResolver实现,ExceptionHandlerExceptionResolver,
ResponseStatusExceptionResolver,DefaultHandlerExceptionResolver。
七、初始化RequestToViewNameTranslator视图转化器
初始化处理适配器initRequestToViewNameTranslator(context), DispatcherServlet#initRequestToViewNameTranslator核心伪代码:
1 // RequestToViewNameTranslator对象在MVC容器中的beanName 2 public static final String REQUEST_TO_VIEW_NAME_TRANSLATOR_BEAN_NAME = "viewNameTranslator"; 3 4 // 初始化视图转换器 5 private void initRequestToViewNameTranslator(ApplicationContext context) { 6 try { 7 // 获取容器中beanName为viewNameTranslator,类型为RequestToViewNameTranslator的bean对象 8 this.viewNameTranslator = 9 context.getBean(REQUEST_TO_VIEW_NAME_TRANSLATOR_BEAN_NAME, RequestToViewNameTranslator.class); 10 } 11 catch (NoSuchBeanDefinitionException ex) { 12 // 如果未找到,则获取默认的 RequestToViewNameTranslator 对象,DefaultRequestToViewNameTranslator 13 this.viewNameTranslator = getDefaultStrategy(context, RequestToViewNameTranslator.class); 14 } 15 }
1、获取容器中beanName为viewNameTranslator,类型为RequestToViewNameTranslator的bean对象;
2、若未配置ViewNameTranslator,获取SpringMVC默认的RequestToViewNameTranslator实现,DefaultRequestToViewNameTranslator。
八、初始化ViewResolver视图解析器
初始化处理适配器 initViewResolvers(context), DispatcherServlet#initViewResolvers核心伪代码:
1 // ViewResolver对象在MVC容器中的beanName 2 public static final String VIEW_RESOLVER_BEAN_NAME = "viewResolver"; 3 4 // 初始化视图解析器 5 private void initViewResolvers(ApplicationContext context) { 6 // 置空 viewResolvers 处理 7 this.viewResolvers = null; 8 9 // 自动扫描 ViewResolver 类型的 Bean 10 if (this.detectAllViewResolvers) { 11 // 获取容器中所有ViewResolver类型的bean对象 12 Map<String, ViewResolver> matchingBeans = 13 BeanFactoryUtils.beansOfTypeIncludingAncestors(context, ViewResolver.class, true, false); 14 // 容器中存在ViewResolver类型的bean对象 15 if (!matchingBeans.isEmpty()) { 16 // 添加至viewResolvers集合中 17 this.viewResolvers = new ArrayList<>(matchingBeans.values()); 18 // 排序 19 AnnotationAwareOrderComparator.sort(this.viewResolvers); 20 } 21 } 22 // 获得名字为VIEW_RESOLVER_BEAN_NAME的bean 23 else { 24 // 获取容器中beanName为viewResolver, 类型为ViewResolver的bean对象 25 ViewResolver vr = context.getBean(VIEW_RESOLVER_BEAN_NAME, ViewResolver.class); 26 // 添加至viewResolvers集合中 27 this.viewResolvers = Collections.singletonList(vr); 28 } 29 30 // 如果未配置视图解析器ViewResolver,则获取默认配置的ViewResolver对象InternalResourceViewResolver 31 if (this.viewResolvers == null) { 32 this.viewResolvers = getDefaultStrategies(context, ViewResolver.class); 33 } 34 }
九、初始化FlashMapManager缓存管理器
主要用于重定向时的参数传递。
初始化缓存管理器 initFlashMapManager(context), DispatcherServlet#initFlashMapManager核心伪代码:
1 // FlashMapManager对象在MVC容器中的beanName 2 public static final String FLASH_MAP_MANAGER_BEAN_NAME = "flashMapManager"; 3 4 // 初始化缓存管理器 5 private void initFlashMapManager(ApplicationContext context) { 6 try { 7 // 获取容器中beanName为flashMapManager,类型为FlashMapManager的bean对象 8 this.flashMapManager = context.getBean(FLASH_MAP_MANAGER_BEAN_NAME, FlashMapManager.class); 9 } 10 catch (NoSuchBeanDefinitionException ex) { 11 // 未找到,则获取默认的 FlashMapManager 对象,SessionFlashMapManager 12 this.flashMapManager = getDefaultStrategy(context, FlashMapManager.class); 13 } 14 }
十、DispatcherServlet默认的策略实现
1 # DispatcherServlet的策略接口的默认实现类 2 3 org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver 4 5 org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver 6 7 org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\ 8 org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping,\ 9 org.springframework.web.servlet.function.support.RouterFunctionMapping 10 11 org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\ 12 org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\ 13 org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter,\ 14 org.springframework.web.servlet.function.support.HandlerFunctionAdapter 15 16 17 org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver,\ 18 org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\ 19 org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver 20 21 org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator 22 23 org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver 24 25 org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager
针对九大组件,获取默认的策略实现,在DispatcherServlet.properties文件中有具体配置,只要根据对应的namespace获取到对应实现类即可。