背景
在初始化整体流程文章中,只是介绍了流程,并且没有对各个组件的初始化以及请求流程做详细的介绍,本章主要是介绍下初始化的流程:
详细介绍
整体初始化过程
在DispatcherServlet的initStrategies初始了Springmvc的9大组件:
/**
* 初始化此servlet使用的策略对象。
* 以便初始化进一步的策略对象
* 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) {
// 初始化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.
* <p>如果没有在命名空间定义,则默认使用BeanNameUrlHandlerMapping.
*/
private void initHandlerMappings(ApplicationContext context) {
this.handlerMappings = null;
if (this.detectAllHandlerMappings) {
// 查找ApplicationContext中的所有HandlerMappings,包括父上下文
Map<String, HandlerMapping> 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工作流程,每个处理类的适配接口
/**
* 初始化.
* <p>if 不存在 则用 SimpleControllerHandlerAdapter.
*/
private void initHandlerAdapters(ApplicationContext context) {
this.handlerAdapters = null;
if (this.detectAllHandlerAdapters) {
// Find all HandlerAdapters in the ApplicationContext, including ancestor contexts.
Map<String, HandlerAdapter> matchingBeans =
BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false);
if (!matchingBeans.isEmpty()) {
this.handlerAdapters = new ArrayList<HandlerAdapter>(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的组件初始化流程基本一样