1. 程式人生 > >SpringMVC5原始碼AnnotationDrivenBeanDefinitionParser註解解析器

SpringMVC5原始碼AnnotationDrivenBeanDefinitionParser註解解析器

    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());