目录
前言
上一篇我们已经完成了springmvc中子容器的初始化,子容器里面一般是一些和web相关的组件,其中的配置文件中就有mvc:annotation-driven
这个标签,这里主要对这个标签来进行剖析,看下它里面干了一些什么,其实也是为了后面我们能通过请求url找到对应处理器方法完成的一个铺垫
mvc:annotation-driven标签概述
mvc:annotation-driven标签默认会开启SpringMVC的注解驱动模式,默认注册一个RequestMappingHandlerMapping、一个RequestMappingHandlerAdapter、一个ExceptionHandlerExceptionResolver。以支持对使用了 @RequestMapping 、 @ExceptionHandler 及其他注解的控制器方法的请求处理。
mvc:annotation-driven标签解析【RequestMappingHandlerMapping生成】
首先这是一个XML标签,所以我们需要到Spring中refresh()
核心方法中的obtainFreshBeanFactory()
中里面的parseBeanDefinitions(root,delegate)
方法那里打断点,找到解析 mvc:annotation-driven
这个标签的逻辑
注意:node一定得是 mvc:annotation-driven这个标签
public BeanDefinition parseCustomElement(Element ele) {
return parseCustomElement(ele, null);
}
public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
//解析节点的命名空间
String namespaceUri = getNamespaceURI(ele);
if (namespaceUri == null) {
return null;
}
//解析命名空间,得到一个命名空间处理器
//重点
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
if (handler == null) {
error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
return null;
}
//开始解析
//主线 重点
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));\
}
public BeanDefinition parse(Element element, ParserContext parserContext) {
//通过定义的标签属性(如:component-scan)获取对应的BeanDefinitionParser解析对象
BeanDefinitionParser parser = findParserForElement(element, parserContext);
//执行解析 AnnotationDrivenBeanDefinitionParser.parse
return (parser != null ? parser.parse(element, parserContext) : null);
}
关于定位自定义标签解析的过程,以后的IOC中会说明的,这里直接打开AnnotationDrivenBeanDefinitionParser
类并定位到其parse方法
AnnotationDrivenBeanDefinitionParser#parse (解析入口)
/**
* 解析 mvc:annotation-driven 标签
*/
@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {
Object source = parserContext.extractSource(element);
XmlReaderContext readerContext = parserContext.getReaderContext();
CompositeComponentDefinition compDefinition = new CompositeComponentDefinition(element.getTagName(), source);
parserContext.pushContainingComponent(compDefinition);
/**
* 获取协商内容视图配置
*/
RuntimeBeanReference contentNegotiationManager = getContentNegotiationManager(element, source, parserContext);
/**
* 创建RequestMappingHandlerMapping的RootBeanDefinition
* 从这里也可以看出,开启mvc:annotation-driven标签后,
* 将会默认注册RequestMappingHandlerMapping作为默认的HandlerMapping
*/
RootBeanDefinition handlerMappingDef = new RootBeanDefinition(RequestMappingHandlerMapping.class);
handlerMappingDef.setSource(source);
handlerMappingDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
handlerMappingDef.getPropertyValues().add("order", 0);
handlerMappingDef.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager);
// 是否开启矩阵变量
if (element.hasAttribute("enable-matrix-variables")) {
Boolean enableMatrixVariables = Boolean.valueOf(element.getAttribute("enable-matrix-variables"));
handlerMappingDef.getPropertyValues().add("removeSemicolonContent", !enableMatrixVariables);
}
// 解析path-matching路径匹配标签
configurePathMatchingProperties(handlerMappingDef, element, parserContext);
readerContext.getRegistry().registerBeanDefinition(HANDLER_MAPPING_BEAN_NAME , handlerMappingDef);
// 解析cors跨域标签
RuntimeBeanReference corsRef = MvcNamespaceUtils.registerCorsConfigurations(null, parserContext, source);
handlerMappingDef.getPropertyValues().add("corsConfigurations", corsRef);
// 解析conversion-service数据转换、格式化标签
RuntimeBeanReference conversionService = getConversionService(element, source, parserContext);
// 解析validator标签
RuntimeBeanReference validator = getValidator(element, source, parserContext);
// 解析message-codes-resolver标签
RuntimeBeanReference messageCodesResolver = getMessageCodesResolver(element);
/**
* 创建ConfigurableWebBindingInitializer的RootBeanDefinition对象
* 并将上一步解析的conversionService、validator、messageCodesResolver
* 作为属性注入到该对象中
*/
RootBeanDefinition bindingDef = new RootBeanDefinition(ConfigurableWebBindingInitializer.class);
bindingDef.setSource(source);
bindingDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
bindingDef.getPropertyValues().add("conversionService", conversionService);
bindingDef.getPropertyValues().add("validator", validator);
bindingDef.getPropertyValues().add("messageCodesResolver", messageCodesResolver);
// 解析message-converters标签
ManagedList<?> messageConverters = getMessageConverters(element, source, parserContext);
// 解析argument-resolvers标签
ManagedList<?> argumentResolvers = getArgumentResolvers(element, parserContext);
// 解析return-value-handlers标签
ManagedList<?> returnValueHandlers = getReturnValueHandlers(element, parserContext);
// 解析async-support标签
String asyncTimeout = getAsyncTimeout(element);
// 解析async-support的task-executor子标签
RuntimeBeanReference asyncExecutor = getAsyncExecutor(element);
// 解析async-support的callable-interceptors子标签
ManagedList<?> callableInterceptors = getCallableInterceptors(element, source, parserContext);
// 解析async-support的deferred-result-interceptors子标签
ManagedList<?> deferredResultInterceptors = getDeferredResultInterceptors(element, source, parserContext);
/**
* 创建RequestMappingHandlerAdapter的RootBeanDefinition
* 从这里也可以看出,开启mvc:annotation-driven标签后,
* 将会默认注册RequestMappingHandlerAdapter作为默认的HandlerAdapter
* 并将上面解析的内容绑定到该HandlerAdapter中
*/
RootBeanDefinition handlerAdapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class);
handlerAdapterDef.setSource(source);
handlerAdapterDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
handlerAdapterDef.getPropertyValues().add("contentNegotiationManager", content