SpringMVC5原始碼AnnotationDrivenBeanDefinitionParser註解解析器
阿新 • • 發佈:2018-11-28
mvc:annotation-driven節點的解析器,是springmvc的核心解析器。AnnotationDrivenBeanDefinitionParser類包路徑是org.springframework.web.servlet.config,繼承於BeanDefinitionParser介面。
1、說明
通過AnnotationDrivenBeanDefinitionParser註解解析器原始碼發現,主要註冊HandlerMappings-路徑匹配器、HandlerAdapters-路徑匹配介面卡、HandlerExceptionResolvers
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());