mvc:annotation-driven节点的解析器,是springmvc的核心解析器。AnnotationDrivenBeanDefinitionParser类包路径是org.springframework.web.servlet.config,继承于BeanDefinitionParser接口。
1、说明
通过AnnotationDrivenBeanDefinitionParser注解解析器源码发现,主要注册HandlerMappings-路径匹配器、HandlerAdapters-路径匹配适配器、HandlerExceptionResolvers-异常解析器、AntPathMatcher-路径解析器、UrlPathHelper-请求路径获取帮助类等beans,提前为mvc做好基础的准备。
AnnotationDrivenBeanDefinitionParser注解解析器注入了类包括:RequestMappingHandlerMapping、BeanNameUrlHandlerMapping、RequestMappingHandlerAdapter、HttpRequestHandlerAdapter、SimpleControllerHandlerAdapter、ExceptionHandlerExceptionResolver、ResponseStatusExceptionResolver、DefaultHandlerExceptionResolver。
2、parse()方法
2.1、registerComponent
跟官方注释提及的一样,主要目的是注册与mvc处理有关的相关beans以及默认的mvc组件.
parserContext.registerComponent(new BeanComponentDefinition(handlerMappingDef, HANDLER_MAPPING_BEAN_NAME));
parserContext.registerComponent(new BeanComponentDefinition(handlerAdapterDef, HANDLER_ADAPTER_BEAN_NAME));
parserContext.registerComponent(new BeanComponentDefinition(uriContributorDef, uriContributorName));
parserContext.registerComponent(new BeanComponentDefinition(mappedInterceptorDef, mappedInterceptorName));
//格式转换处理拦截类,比如时间、数字等
parserContext.registerComponent(new BeanComponentDefinition(methodExceptionResolver, methodExResolverName));
parserContext.registerComponent(new BeanComponentDefinition(statusExceptionResolver, statusExResolverName));
parserContext.registerComponent(new BeanComponentDefinition(defaultExceptionResolver, defaultExResolverName));
2.2、组件注册
组件注册对应parse()方法的代码片段如下
//生成RequestMappingHandlerMapping组件对象
RootBeanDefinition handlerMappingDef = new RootBeanDefinition(RequestMappingHandlerMapping.class);
handlerMappingDef.setSource(source);
handlerMappingDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
//优先级设置为最高
handlerMappingDef.getPropertyValues().add("order", 0);
handlerMappingDef.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager);
//查看mvc:annotation-driven有无enable-matrix-variables/enableMatrixVariables,表示是否开启多变量映射比如/user;name=zhangsan;pwd=123
if (element.hasAttribute("enable-matrix-variables")) {
Boolean enableMatrixVariables = Boolean.valueOf(element.getAttribute("enable-matrix-variables"));
handlerMappingDef.getPropertyValues().add("removeSemicolonContent", !enableMatrixVariables);
}
//配置路径匹配解析器等属性
configurePathMatchingProperties(handlerMappingDef, element, parserContext);
4、getMessageConverters方法
自定义的一些参数解析器(HandlerMethodArgumentResolver的实现类)
//parse方法中的
ManagedList<?> messageConverters = getMessageConverters(element, source, parserContext);
private ManagedList<?> getMessageConverters(Element element, @Nullable Object source, ParserContext parserContext) {
Element convertersElement = DomUtils.getChildElementByTagName(element, "message-converters");
//存放自己配置的HttpMessageConverter
ManagedList<? super Object> messageConverters = new ManagedList<>();
if (convertersElement != null) {
messageConverters.setSource(source);
//解析自己配置的HttpMessageConverter的bean
for (Element beanElement : DomUtils.getChildElementsByTagName(convertersElement, "bean", "ref")) {
Object object = parserContext.getDelegate().parsePropertySubElement(beanElement, null);
messageConverters.add(object);
}
}
//如果没有配置<mvc:message-converters>或者register-defaults的值为true 默认为true
if (convertersElement == null || Boolean.valueOf(convertersElement.getAttribute("register-defaults"))) {
messageConverters.setSource(source);
//添加ByteArrayHttpMessageConverter的BeanDefinition messageConverters.add(createConverterDefinition(ByteArrayHttpMessageConverter.class, source));
//添加StringHttpMessageConverter的BeanDefinition
RootBeanDefinition stringConverterDef = createConverterDefinition(StringHttpMessageConverter.class, source);
stringConverterDef.getPropertyValues().add("writeAcceptCharset", false);
messageConverters.add(stringConverterDef);
//添加ResourceHttpMessageConverter的BeanDefinition messageConverters.add(createConverterDefinition(ResourceHttpMessageConverter.class, source));
//添加SourceHttpMessageConverter的BeanDefinition messageConverters.add(createConverterDefinition(ResourceRegionHttpMessageConverter.class, source));
messageConverters.add(createConverterDefinition(SourceHttpMessageConverter.class, source));
messageConverters.add(createConverterDefinition(AllEncompassingFormHttpMessageConverter.class, source));
if (romePresent) {
messageConverters.add(createConverterDefinition(AtomFeedHttpMessageConverter.class, source));
messageConverters.add(createConverterDefinition(RssChannelHttpMessageConverter.class, source));
}
//如果有Classpath下面有 com.fasterxml.jackson.dataformat.xml.XmlMapper,则添加
//MappingJackson2XmlHttpMessageConverter和RssChannelHttpMessageConverter的BeanDefinition
if (jackson2XmlPresent) {
Class<?> type = MappingJackson2XmlHttpMessageConverter.class;
//创建Jackson2ObjectMapperFactoryBean的BeanDefinition
RootBeanDefinition jacksonConverterDef = createConverterDefinition(type, source);
GenericBeanDefinition jacksonFactoryDef = createObjectMapperFactoryDefinition(source);
jacksonFactoryDef.getPropertyValues().add("createXmlMapper", true);
jacksonConverterDef.getConstructorArgumentValues().addIndexedArgumentValue(0, jacksonFactoryDef);
messageConverters.add(jacksonConverterDef);
}
//如果有Classpath下面有 javax.xml.bind.Binder,则添加
//Jaxb2RootElementHttpMessageConverter的BeanDefinition
else if (jaxb2Present) {
messageConverters.add(createConverterDefinition(Jaxb2RootElementHttpMessageConverter.class, source));
}
//如果有Classpath下面有 com.fasterxml.jackson.databind.ObjectMapper和Jaxb2RootElementHttpMessageConverter的BeanDefinition,则添加
//MappingJackson2HttpMessageConverter的BeanDefinition
if (jackson2Present) {
Class<?> type = MappingJackson2HttpMessageConverter.class;
RootBeanDefinition jacksonConverterDef = createConverterDefinition(type, source);
GenericBeanDefinition jacksonFactoryDef = createObjectMapperFactoryDefinition(source);
jacksonConverterDef.getConstructorArgumentValues().addIndexedArgumentValue(0, jacksonFactoryDef);
messageConverters.add(jacksonConverterDef);
}
//如果有Classpath下面有 com.google.gson.Gson,则添加
//GsonHttpMessageConverter的BeanDefinition
else if (gsonPresent) {
messageConverters.add(createConverterDefinition(GsonHttpMessageConverter.class, source));
}
if (jackson2SmilePresent) {
Class<?> type = MappingJackson2SmileHttpMessageConverter.class;
RootBeanDefinition jacksonConverterDef = createConverterDefinition(type, source);
GenericBeanDefinition jacksonFactoryDef = createObjectMapperFactoryDefinition(source);
jacksonFactoryDef.getPropertyValues().add("factory", new SmileFactory());
jacksonConverterDef.getConstructorArgumentValues().addIndexedArgumentValue(0, jacksonFactoryDef);
messageConverters.add(jacksonConverterDef);
}
if (jackson2CborPresent) {
Class<?> type = MappingJackson2CborHttpMessageConverter.class;
RootBeanDefinition jacksonConverterDef = createConverterDefinition(type, source);
GenericBeanDefinition jacksonFactoryDef = createObjectMapperFactoryDefinition(source);
jacksonFactoryDef.getPropertyValues().add("factory", new CBORFactory());
jacksonConverterDef.getConstructorArgumentValues().addIndexedArgumentValue(0, jacksonFactoryDef);
messageConverters.add(jacksonConverterDef);
}
}
return messageConverters;
}
以上代码对应了下面
private static final boolean javaxValidationPresent =
ClassUtils.isPresent("javax.validation.Validator",AnnotationDrivenBeanDefinitionParser.class.getClassLoader());
private static boolean romePresent =
ClassUtils.isPresent("com.rometools.rome.feed.WireFeed",AnnotationDrivenBeanDefinitionParser.class.getClassLoader());
private static final boolean jaxb2Present =
ClassUtils.isPresent("javax.xml.bind.Binder",AnnotationDrivenBeanDefinitionParser.class.getClassLoader());
private static final boolean jackson2Present =
ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper",
AnnotationDrivenBeanDefinitionParser.class.getClassLoader()) &&
ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator",AnnotationDrivenBeanDefinitionParser.class.getClassLoader());
private static final boolean jackson2XmlPresent =
ClassUtils.isPresent("com.fasterxml.jackson.dataformat.xml.XmlMapper",AnnotationDrivenBeanDefinitionParser.class.getClassLoader());
private static final boolean jackson2SmilePresent =
ClassUtils.isPresent("com.fasterxml.jackson.dataformat.smile.SmileFactory",AnnotationDrivenBeanDefinitionParser.class.getClassLoader());
private static final boolean jackson2CborPresent =
ClassUtils.isPresent("com.fasterxml.jackson.dataformat.cbor.CBORFactory",AnnotationDrivenBeanDefinitionParser.class.getClassLoader());
private static final boolean gsonPresent =
ClassUtils.isPresent("com.google.gson.Gson",AnnotationDrivenBeanDefinitionParser.class.getClassLoader());