Dispatcher中有几个引用类型的属性:SpringMVC的九大组件
SpringMVC在工作的时候,关键位置都是由这些组件完成的
public class DispatcherServlet extends FrameworkServlet {
//文件上传解析器
@Nullable
private MultipartResolver multipartResolver;
//区域信息解析器(国际化有关)
@Nullable
private LocaleResolver localeResolver;
//主题解析器:强大的主题效果更换
@Nullable
private ThemeResolver themeResolver;
//Handler映射信息(controller)
@Nullable
private List<HandlerMapping> handlerMappings;
//Handler的适配器
@Nullable
private List<HandlerAdapter> handlerAdapters;
//处理器异常解析器 —— SpringMVC强大的异常解析功能
@Nullable
private List<HandlerExceptionResolver> handlerExceptionResolvers;
//请求视图名转换(void) 没啥用
@Nullable
private RequestToViewNameTranslator viewNameTranslator;
//FlashMap + Manager SpringMVC允许重定向携带数据的功能
@Nullable
private FlashMapManager flashMapManager;
//视图解析器
@Nullable
private List<ViewResolver> viewResolvers;
}
共同点:九大组件全是接口,接口就是规范,提供了很强的扩展性
DispatcherServlet中九大组件初始化的地方
@Override
protected void onRefresh(ApplicationContext context) {
initStrategies(context);
}
protected void initStrategies(ApplicationContext context) {
//九大组件初始化的地方
initMultipartResolver(context);
initLocaleResolver(context);
initThemeResolver(context);
initHandlerMappings(context);
initHandlerAdapters(context);
initHandlerExceptionResolvers(context);
initRequestToViewNameTranslator(context);
initViewResolvers(context);
initFlashMapManager(context);
}
下面以初始化initHandlerMappings(context);为例来看一下
private void initHandlerMappings(ApplicationContext context) {
this.handlerMappings = null;
//this.detectAllHandlerMappings默认为true(上面写死的,可在配置文件中修改)
if (this.detectAllHandlerMappings) {
//找IOC中所有的 HandlerMapping
Map<String, HandlerMapping> matchingBeans =
BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
//找到了 就赋值属性
if (!matchingBeans.isEmpty()) {
this.handlerMappings = new ArrayList<>(matchingBeans.values());
// We keep HandlerMappings in sorted order.
AnnotationAwareOrderComparator.sort(this.handlerMappings);
}
}
//this.detectAllHandlerMappings不为true 则在IOC中找对应ID的HandlerMapping
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
if (this.handlerMappings == null) {
this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
if (logger.isTraceEnabled()) {
logger.trace("No HandlerMappings declared for servlet '" + getServletName() +
"': using default strategies from DispatcherServlet.properties");
}
}
}
如果没有HandlerMapping采取的默认策略:加载该类下的DispatcherServlet.properties配置作为默认策略
private static final Properties defaultStrategies;
static {
try {
ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, DispatcherServlet.class);
defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);
}
catch (IOException ex) {
throw new IllegalStateException("Could not load '" + DEFAULT_STRATEGIES_PATH + "': " + ex.getMessage());
}
}
总结:组件的初始化就是去容器中找到这个组件,如果没有找到就用默认配置或者不配置