[SpringMVC]初始化HandlerMapping、HandlerAdapter

背景

在初始化整体流程文章中,只是介绍了流程,并且没有对各个组件的初始化以及请求流程做详细的介绍,本章主要是介绍下初始化的流程:

详细介绍

整体初始化过程

在DispatcherServlet的initStrategies初始了Springmvc的9大组件:

   /**
     * 初始化此servlet使用的策略对象。
     * 以便初始化进一步的策略对象
     * Initialize the strategy objects that this servlet uses.
     * 

May be overridden in subclasses in order to initialize further strategy objects. */ protected void initStrategies(ApplicationContext context) { // 初始化MultipartResolver 用来处理上传文件 默认是没有处理的,需要在上下文添加MultipartResolver处理器 // org.springframework.web.multipart.commons.CommonsMultipartResolver // org.springframework.web.multipart.support.ByteArrayMultipartFileEditor // org.springframework.web.multipart.support.StringMultipartFileEditor initMultipartResolver(context); // 初始化LocaleResolver 配置国际化的 initLocaleResolver(context); // 初始化ThemeResolver 通过主题控制页面风格 initThemeResolver(context); // 初始化HandlerMappings 由定义请求和处理程序对象之间映射的对象实现 initHandlerMappings(context); // 初始化HandlerAdapters initHandlerAdapters(context); // 初始化HandlerExceptionResolvers 异常处理 initHandlerExceptionResolvers(context); // 初始化RequestToViewNameTranslator initRequestToViewNameTranslator(context); // 初始化ViewResolvers initViewResolvers(context); // 初始化FlashMapManager initFlashMapManager(context); }

初始化HandleMapping

HandlerMapping是什么?

定义请求和处理程序对象之间的映射.这个类可以由开发人员实现,框架已经开发了org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping和org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping。如果在应用程序上下文中没有注册HandlerMapping bean,则前者是默认值。
HandlerMapping实现可以支持映射的拦截器

/**
     * 初始化 HandlerMappings.
     * 

如果没有在命名空间定义,则默认使用BeanNameUrlHandlerMapping. */ private void initHandlerMappings(ApplicationContext context) { this.handlerMappings = null; if (this.detectAllHandlerMappings) { // 查找ApplicationContext中的所有HandlerMappings,包括父上下文 Map matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false); if (!matchingBeans.isEmpty()) { this.handlerMappings = new ArrayList<>(matchingBeans.values()); // 按照优先级排序. AnnotationAwareOrderComparator.sort(this.handlerMappings); } } else { try { HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class); this.handlerMappings = Collections.singletonList(hm); } catch (NoSuchBeanDefinitionException ex) { // Ignore, we'll add a default HandlerMapping later. } } // 通过注册确保我们至少有一个HandlerMapping 如果找不到其他映射,则使用默认的HandlerMapping if (this.handlerMappings == null) { this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class); if (logger.isDebugEnabled()) { logger.debug("No HandlerMappings found in servlet '" + getServletName() + "': using default"); } } }

这个简单吧,下面看下HandlerAdapter的初始化。理解了上面的,HandlerAdapter就很简单了

HandlerAdapter

HandlerAdapter是什么?

MVC框架SPI,允许参数化核心MVC工作流程,每个处理类的适配接口

 /**
     * 初始化.
     * 

if 不存在 则用 SimpleControllerHandlerAdapter. */ private void initHandlerAdapters(ApplicationContext context) { this.handlerAdapters = null; if (this.detectAllHandlerAdapters) { // Find all HandlerAdapters in the ApplicationContext, including ancestor contexts. Map matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false); if (!matchingBeans.isEmpty()) { this.handlerAdapters = new ArrayList(matchingBeans.values()); // We keep HandlerAdapters in sorted order. OrderComparator.sort(this.handlerAdapters); } } else { try { HandlerAdapter ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME, HandlerAdapter.class); this.handlerAdapters = Collections.singletonList(ha); } catch (NoSuchBeanDefinitionException ex) { // Ignore, we'll add a default HandlerAdapter later. } } // Ensure we have at least some HandlerAdapters, by registering // default HandlerAdapters if no other adapters are found. if (this.handlerAdapters == null) { this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class); if (logger.isDebugEnabled()) { logger.debug("No HandlerAdapters found in servlet '" + getServletName() + "': using default"); } } }

总结

这个两个方法流程上基本上相同,主要用到了两个静态方法

BeanFactoryUtils#beansOfTypeIncludingAncestors

根据给定的类型或者子类类型返回所有bean
如果当前的bean工厂是HierarchicalBeanFactory,也会获取在祖先bean工厂中定义的bean
递归获取

Spring提供了很多工具类很好用,我们平常开发过程中,不用再重复造轮子,不过最好知道Spring的内部实现,比如:BeanFactoryUtils、AnnotationUtils、ClassUtils、BeanUtils、ReflectionUtils、ResourceUtils等

DispatcherServlet#getDefaultStrategies

创建一个给定的策略接口的默认策略对象
1、根据参数strategyInterface从DispatcherServlet.properties文件查询(提前初始化好)对象的类列表
2、通过Class.forName实例化

其他

其他Springmvc的组件初始化流程基本一样

你可能感兴趣的:([SpringMVC]初始化HandlerMapping、HandlerAdapter)