首页 > 编程语言 >SpringMVC源码(三):九大内置组件初始化

SpringMVC源码(三):九大内置组件初始化

时间:2023-02-12 20:44:06浏览次数:65  
标签:初始化 web SpringMVC springframework bean 源码 context servlet

  在源码(二):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对象。

三、初始化主题资源

  初始化主题资源initThemeResolver(context),DispatcherServlet#initThemeResolver核心伪代码:
 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默认的策略实现

  可以查看Spring-webmvc子模块中的DispatcherServlet.properties文件,详情如下:
 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获取到对应实现类即可。

 

标签:初始化,web,SpringMVC,springframework,bean,源码,context,servlet
From: https://www.cnblogs.com/RunningSnails/p/17114661.html

相关文章

  • drf_jwt源码执行流程-自定义用户表签发和认证-simpleui的使用-权限控制(acl,rbac)
    目录drf_jwt源码执行流程-自定义用户表签发和认证-simpleui的使用-权限控制(acl,rbac)昨日内容回顾今日概要今日详细1drf-jwt源码执行流程(了解)1.1签发(登录)1.2认证(......
  • 权限源码分析、认证源码分析、频率源码分析、异常处理、异常处理、jwt介绍和原理、drf
    权限源码分析写一个权限类局部使用配置在视图类的就会执行权限类的permission_classes方法完成权限校验'''drf的APIView源码执行流程: 1.先匹配路由APIView中as_vie......
  • DispatcherServlet源码解析
    DispatcherServlet中使用的默认策略接口DispatcherServlet.properties中指定了DispatcherServlet.java中使用的一些策略接口的默认实现:spring-webmvc-5.3.9.jar!/org/s......
  • [16] Zookeeper-源码2
    1.ZkServer选举源码1.1选举准备QuorumPeer@Overridepublicsynchronizedvoidstart(){if(!getView().containsKey(myid)){thrownewRuntimeEx......
  • Kubernetes CSI插件注册(一)—— node-driver-registrar源码分析
    1、概述node-driver-registrar是一个由官方K8ssig小组维护的辅助容器(sidecar),它的主要作用则是获取CSI插件信息并通过GRPC服务(即RegistrationServer)向Kubelet提供插件......
  • 初始化列表
    初始化列表构造函数的执行可以分成两个阶段:初始化阶段和计算阶段(初始化阶段先于计算阶段)。l初始化阶段:全部的成员都会在初始化阶段初始化。l计算阶段:一般是指用于执行......
  • Ribbon负载均衡 (源码分析)
    Ribbon负载均衡SpringCloud已经删除了ribbon组件,所以需要手动导入依赖。(要学是因为很多项目业务已经使用了ribbon)服务拉取的时候添加了@LoadBalanced注解,实现负载均衡......
  • StampedLock源码解析
    StampedLock源码解析StampedLock描述一种基于能力的锁,具有三种模式,用于控制读写访问。StampedLock的状态由版本和模式组成。锁获取方法返回一个表示并控制对锁状态访问......
  • Go语言学习11-数据初始化
    数据初始化书接上篇,我们了解了Go语言的指针类型。那到目前为止,Go的数据类型就差不多介绍完了,下面就是讲解更优雅地对Go数据的初始化了。这里的数据初始化是指对某个......
  • [​DuckDB] 多核算子并行的源码解析
    DuckDB是近年来颇受关注的OLAP数据库,号称是OLAP领域的SQLite,以精巧简单,性能优异而著称。笔者前段时间在调研Doris的Pipeline的算子并行方案,而DuckDB基于论文《Morsel-Driv......