SpringMVC源码-mvc:annotation-driven解析
mvc namespace的处理器由webmvc项目下Resources/META-INF/spring.handlers文件:
http\://www.springframework.org/schema/mvc=org.springframework.web.servlet.config.MvcNamespaceHandler
决定。
MvcNamespaceHandler
public class MvcNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
registerBeanDefinitionParser("default-servlet-handler", new DefaultServletHandlerBeanDefinitionParser());
registerBeanDefinitionParser("interceptors", new InterceptorsBeanDefinitionParser());
registerBeanDefinitionParser("resources", new ResourcesBeanDefinitionParser());
registerBeanDefinitionParser("view-controller", new ViewControllerBeanDefinitionParser());
registerBeanDefinitionParser("redirect-view-controller", new ViewControllerBeanDefinitionParser());
registerBeanDefinitionParser("status-controller", new ViewControllerBeanDefinitionParser());
registerBeanDefinitionParser("view-resolvers", new ViewResolversBeanDefinitionParser());
registerBeanDefinitionParser("tiles-configurer", new TilesConfigurerBeanDefinitionParser());
registerBeanDefinitionParser("freemarker-configurer", new FreeMarkerConfigurerBeanDefinitionParser());
registerBeanDefinitionParser("groovy-configurer", new GroovyMarkupConfigurerBeanDefinitionParser());
registerBeanDefinitionParser("script-template-configurer", new ScriptTemplateConfigurerBeanDefinitionParser());
registerBeanDefinitionParser("cors", new CorsBeanDefinitionParser());
}
}
annotation-driven标签由AnnotationDrivenBeanDefinitionParser解析。
AnnotationDrivenBeanDefinitionParser
static {
ClassLoader classLoader = AnnotationDrivenBeanDefinitionParser.class.getClassLoader();
javaxValidationPresent = ClassUtils.isPresent("javax.validation.Validator", classLoader); // 类路径是否存在Validator校验
romePresent = ClassUtils.isPresent("com.rometools.rome.feed.WireFeed", classLoader); // 类路径是否存在WireFeed
jaxb2Present = ClassUtils.isPresent("javax.xml.bind.Binder", classLoader); // 类路径是否存在Binder
jackson2Present = ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", classLoader) &&
ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", classLoader); // 类路径是否存在jackson 序列化类ObjectMapper
jackson2XmlPresent = ClassUtils.isPresent("com.fasterxml.jackson.dataformat.xml.XmlMapper", classLoader); //类路径是否存在XmlMapper-jackson 处理xml
jackson2SmilePresent = ClassUtils.isPresent("com.fasterxml.jackson.dataformat.smile.SmileFactory", classLoader); //类路径是否存在SmileFactory-处理二进制类似JSON数据
jackson2CborPresent = ClassUtils.isPresent("com.fasterxml.jackson.dataformat.cbor.CBORFactory", classLoader); // 类路径是否存在CBORFactory-解析CBOR数据格式
gsonPresent = ClassUtils.isPresent("com.google.gson.Gson", classLoader); // 类路径是否存在Gson序列化
}
AnnotationDrivenBeanDefinitionParser.parse(Element element, ParserContext context)
public BeanDefinition parse(Element element, ParserContext context) {
Object source = context.extractSource(element);
XmlReaderContext readerContext = context.getReaderContext();
CompositeComponentDefinition compDefinition = new CompositeComponentDefinition(element.getTagName(), source);
context.pushContainingComponent(compDefinition);
RuntimeBeanReference contentNegotiationManager = getContentNegotiationManager(element, source, context);
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.parseBoolean(element.getAttribute("enable-matrix-variables"));
handlerMappingDef.getPropertyValues().add("removeSemicolonContent", !enableMatrixVariables);
}
configurePathMatchingProperties(handlerMappingDef, element, context);
readerContext.getRegistry().registerBeanDefinition(HANDLER_MAPPING_BEAN_NAME, handlerMappingDef);
RuntimeBeanReference corsRef = MvcNamespaceUtils.registerCorsConfigurations(null, context, source);
handlerMappingDef.getPropertyValues().add("corsConfigurations", corsRef);
RuntimeBeanReference conversionService = getConversionService(element, source, context);
RuntimeBeanReference validator = getValidator(element, source, context);
RuntimeBeanReference messageCodesResolver = getMessageCodesResolver(element);
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);
ManagedList<?> messageConverters = getMessageConverters(element, source, context);
ManagedList<?> argumentResolvers = getArgumentResolvers(element, context);
ManagedList<?> returnValueHandlers = getReturnValueHandlers(element, context);
String asyncTimeout = getAsyncTimeout(element);
RuntimeBeanReference asyncExecutor = getAsyncExecutor(element);
ManagedList<?> callableInterceptors = getInterceptors(element, source, context, "callable-interceptors");
ManagedList<?> deferredResultInterceptors = getInterceptors(element, source, context, "deferred-result-interceptors");
RootBeanDefinition handlerAdapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class);
handlerAdapterDef.setSource(source);
handlerAdapterDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
handlerAdapterDef.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager);
handlerAdapterDef.getPropertyValues().add("webBindingInitializer", bindingDef);
handlerAdapterDef.getPropertyValues().add("messageConverters", messageConverters);
addRequestBodyAdvice(handlerAdapterDef);
addResponseBodyAdvice(handlerAdapterDef);
if (element.hasAttribute("ignore-default-model-on-redirect")) {
Boolean ignoreDefaultModel = Boolean.valueOf(element.getAttribute("ignore-default-model-on-redirect"));
handlerAdapterDef.getPropertyValues().add("ignoreDefaultModelOnRedirect", ignoreDefaultModel);
}
if (argumentResolvers != null) {
handlerAdapterDef.getPropertyValues().add("customArgumentResolvers", argumentResolvers);
}
if (returnValueHandlers != null) {
handlerAdapterDef.getPropertyValues().add("customReturnValueHandlers", returnValueHandlers);
}
if (asyncTimeout != null) {
handlerAdapterDef.getPropertyValues().add("asyncRequestTimeout", asyncTimeout);
}
if (asyncExecutor != null) {
handlerAdapterDef.getPropertyValues().add("taskExecutor", asyncExecutor);
}
handlerAdapterDef.getPropertyValues().add("callableInterceptors", callableInterceptors);
handlerAdapterDef.getPropertyValues().add("deferredResultInterceptors", deferredResultInterceptors);
readerContext.getRegistry().registerBeanDefinition(HANDLER_ADAPTER_BEAN_NAME, handlerAdapterDef);
RootBeanDefinition uriContributorDef =
new RootBeanDefinition(CompositeUriComponentsContributorFactoryBean.class);
uriContributorDef.setSource(source);
uriContributorDef.getPropertyValues().addPropertyValue("handlerAdapter", handlerAdapterDef);
uriContributorDef.getPropertyValues().addPropertyValue("conversionService", conversionService);
String uriContributorName = MvcUriComponentsBuilder.MVC_URI_COMPONENTS_CONTRIBUTOR_BEAN_NAME;
readerContext.getRegistry().registerBeanDefinition(uriContributorName, uriContributorDef);
RootBeanDefinition csInterceptorDef = new RootBeanDefinition(ConversionServiceExposingInterceptor.class);
csInterceptorDef.setSource(source);
csInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(0, conversionService);
RootBeanDefinition mappedInterceptorDef = new RootBeanDefinition(MappedInterceptor.class);
mappedInterceptorDef.setSource(source);
mappedInterceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
mappedInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(0, (Object) null);
mappedInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(1, csInterceptorDef);
String mappedInterceptorName = readerContext.registerWithGeneratedName(mappedInterceptorDef);
RootBeanDefinition methodExceptionResolver = new RootBeanDefinition(ExceptionHandlerExceptionResolver.class);
methodExceptionResolver.setSource(source);
methodExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
methodExceptionResolver.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager);
methodExceptionResolver.getPropertyValues().add("messageConverters", messageConverters);
methodExceptionResolver.getPropertyValues().add("order", 0);
addResponseBodyAdvice(methodExceptionResolver);
if (argumentResolvers != null) {
methodExceptionResolver.getPropertyValues().add("customArgumentResolvers", argumentResolvers);
}
if (returnValueHandlers != null) {
methodExceptionResolver.getPropertyValues().add("customReturnValueHandlers", returnValueHandlers);
}
String methodExResolverName = readerContext.registerWithGeneratedName(methodExceptionResolver);
RootBeanDefinition statusExceptionResolver = new RootBeanDefinition(ResponseStatusExceptionResolver.class);
statusExceptionResolver.setSource(source);
statusExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
statusExceptionResolver.getPropertyValues().add("order", 1);
String statusExResolverName = readerContext.registerWithGeneratedName(statusExceptionResolver);
RootBeanDefinition defaultExceptionResolver = new RootBeanDefinition(DefaultHandlerExceptionResolver.class);
defaultExceptionResolver.setSource(source);
defaultExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
defaultExceptionResolver.getPropertyValues().add("order", 2);
String defaultExResolverName = readerContext.registerWithGeneratedName(defaultExceptionResolver);
context.registerComponent(new BeanComponentDefinition(handlerMappingDef, HANDLER_MAPPING_BEAN_NAME));
context.registerComponent(new BeanComponentDefinition(handlerAdapterDef, HANDLER_ADAPTER_BEAN_NAME));
context.registerComponent(new BeanComponentDefinition(uriContributorDef, uriContributorName));
context.registerComponent(new BeanComponentDefinition(mappedInterceptorDef, mappedInterceptorName));
context.registerComponent(new BeanComponentDefinition(methodExceptionResolver, methodExResolverName));
context.registerComponent(new BeanComponentDefinition(statusExceptionResolver, statusExResolverName));
context.registerComponent(new BeanComponentDefinition(defaultExceptionResolver, defaultExResolverName));
// Ensure BeanNameUrlHandlerMapping (SPR-8289) and default HandlerAdapters are not "turned off"
MvcNamespaceUtils.registerDefaultComponents(context, source);
context.popAndRegisterContainingComponent();
return null;
}
1、调用getContentNegotiationManager创建ContentNegotiationManagerFactoryBean类型的BeanDefinition
2、创建RequestMappingHandlerMapping类型的RootBeanDefinition
3、为RequestMappingHandlerMapping设置order,contentNegotiationManager,解析enable-matrix-variables并设置removeSemicolonContent属性
4、调用configurePathMatchingProperties设置RequestMappingHandlerMapping属性
5、调用MvcNamespaceUtils.registerCorsConfigurations创建mvcCorsConfigurations RootBeanDefinition
6、RequestMappingHandlerMapping添加属性corsConfigurations
7、调用getConversionService
8、调用getValidator获取验证器RuntimeBeanReference
9、调用getMessageCodesResolver
10.构造类型ConfigurableWebBindingInitializer的RootBeanDefinition并设置conversionService,validator,messageCodesResolver属性
11、调用getMessageConverters获取消息转换器
12、调用getArgumentResolvers
13、调用getReturnValueHandlers解析return-value-handlers属性
14、调用getAsyncTimeout解析async-support和default-timeout属性
15、getAsyncExecutor解析async-support,task-executor,task-executor
16、getInterceptors解析async-support,callable-interceptors属性
17、getInterceptors解析async-support,deferred-result-interceptors属性
18、创建类型为RequestMappingHandlerAdapter的RootBeanDefinition并设置contentNegotiationManager,webBindingInitializer,messageConverters属性
19、调用addRequestBodyAdvice,如果jackson2Present为true,则RequestMappingHandlerAdapter添加类型为JsonViewRequestBodyAdvice的RootBeanDefinition属性
20、调用addResponseBodyAdvice,如果jackson2Present为true,则RequestMappingHandlerAdapter添加类型为JsonViewResponseBodyAdvice的RootBeanDefinition属性
21、解析RequestMappingHandlerAdapter相应属性
22、创建类型为CompositeUriComponentsContributorFactoryBean的RootBeanDefinition
23、创建类型为ConversionServiceExposingInterceptor的RootBeanDefinition
24、创建类型为MappedInterceptor的RootBeanDefinition
25、创建类型为ExceptionHandlerExceptionResolver的RootBeanDefinition
26、创建类型是ResponseStatusExceptionResolver的RootBeanDefinition
27、创建类型是DefaultHandlerExceptionResolver的RootBeanDefinition
28、调用MvcNamespaceUtils.registerDefaultComponents
getContentNegotiationManager(Element element, @Nullable Object source, ParserContext context)
private RuntimeBeanReference getContentNegotiationManager(
Element element, @Nullable Object source, ParserContext context) {
RuntimeBeanReference beanRef;
if (element.hasAttribute("content-negotiation-manager")) {
String name = element.getAttribute("content-negotiation-manager");
beanRef = new RuntimeBeanReference(name);
}
else {
RootBeanDefinition factoryBeanDef = new RootBeanDefinition(ContentNegotiationManagerFactoryBean.class);
factoryBeanDef.setSource(source);
factoryBeanDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
factoryBeanDef.getPropertyValues().add("mediaTypes", getDefaultMediaTypes());
String name = CONTENT_NEGOTIATION_MANAGER_BEAN_NAME;
context.getReaderContext().getRegistry().registerBeanDefinition(name, factoryBeanDef);
context.registerComponent(new BeanComponentDefinition(factoryBeanDef, name));
beanRef = new RuntimeBeanReference(name);
}
return beanRef;
}
1、如果存在content-negotiation-manager属性,返回RuntimeBeanReference
2、创建ContentNegotiationManagerFactoryBean类型的RootBeanDefinition,并设置属性
configurePathMatchingProperties(RootBeanDefinition handlerMappingDef, Element element, ParserContext context)
private void configurePathMatchingProperties(
RootBeanDefinition handlerMappingDef, Element element, ParserContext context) {
Element pathMatchingElement = DomUtils.getChildElementByTagName(element, "path-matching");
if (pathMatchingElement != null) {
Object source = context.extractSource(element);
if (pathMatchingElement.hasAttribute("suffix-pattern")) {
Boolean useSuffixPatternMatch = Boolean.valueOf(pathMatchingElement.getAttribute("suffix-pattern"));
handlerMappingDef.getPropertyValues().add("useSuffixPatternMatch", useSuffixPatternMatch);
}
if (pathMatchingElement.hasAttribute("trailing-slash")) {
Boolean useTrailingSlashMatch = Boolean.valueOf(pathMatchingElement.getAttribute("trailing-slash"));
handlerMappingDef.getPropertyValues().add("useTrailingSlashMatch", useTrailingSlashMatch);
}
if (pathMatchingElement.hasAttribute("registered-suffixes-only")) {
Boolean useRegisteredSuffixPatternMatch = Boolean.valueOf(pathMatchingElement.getAttribute("registered-suffixes-only"));
handlerMappingDef.getPropertyValues().add("useRegisteredSuffixPatternMatch", useRegisteredSuffixPatternMatch);
}
RuntimeBeanReference pathHelperRef = null;
if (pathMatchingElement.hasAttribute("path-helper")) {
pathHelperRef = new RuntimeBeanReference(pathMatchingElement.getAttribute("path-helper"));
}
pathHelperRef = MvcNamespaceUtils.registerUrlPathHelper(pathHelperRef, context, source);
handlerMappingDef.getPropertyValues().add("urlPathHelper", pathHelperRef);
RuntimeBeanReference pathMatcherRef = null;
if (pathMatchingElement.hasAttribute("path-matcher")) {
pathMatcherRef = new RuntimeBeanReference(pathMatchingElement.getAttribute("path-matcher"));
}
pathMatcherRef = MvcNamespaceUtils.registerPathMatcher(pathMatcherRef, context, source);
handlerMappingDef.getPropertyValues().add("pathMatcher", pathMatcherRef);
}
}
1、获取path-matching元素解析成Element
2、如果Element不为null,解析xml配置中suffix-pattern属性设置到handlerMappingDef的useSuffixPatternMatch属性中,解析xml配置中trailing-slash属性设置到handlerMappingDef的useTrailingSlashMatch属性中,解析xml配置中registered-suffixes-only属性设置到handlerMappingDef的useRegisteredSuffixPatternMatch属性中,解析xml配置中path-helper属性成RuntimeBeanReference设置到handlerMappingDef的urlPathHelper属性中,解析xml配置中path-matcher属性成RuntimeBeanReference设置到handlerMappingDef的pathMatcher属性中
MvcNamespaceUtils.registerCorsConfigurations(@Nullable Map<String, CorsConfiguration> corsConfigurations,ParserContext context, @Nullable Object source)
public static RuntimeBeanReference registerCorsConfigurations(
@Nullable Map<String, CorsConfiguration> corsConfigurations,
ParserContext context, @Nullable Object source) {
if (!context.getRegistry().containsBeanDefinition(CORS_CONFIGURATION_BEAN_NAME)) {
RootBeanDefinition corsDef = new RootBeanDefinition(LinkedHashMap.class);
corsDef.setSource(source);
corsDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
if (corsConfigurations != null) {
corsDef.getConstructorArgumentValues().addIndexedArgumentValue(0, corsConfigurations);
}
context.getReaderContext().getRegistry().registerBeanDefinition(CORS_CONFIGURATION_BEAN_NAME, corsDef);
context.registerComponent(new BeanComponentDefinition(corsDef, CORS_CONFIGURATION_BEAN_NAME));
}
else if (corsConfigurations != null) {
BeanDefinition corsDef = context.getRegistry().getBeanDefinition(CORS_CONFIGURATION_BEAN_NAME);
corsDef.getConstructorArgumentValues().addIndexedArgumentValue(0, corsConfigurations);
}
return new RuntimeBeanReference(CORS_CONFIGURATION_BEAN_NAME);
}
1、如果context不包含名为mvcCorsConfigurations的BeanDefinition,创建类型是LinkedHashMap的名为mvcCorsConfigurations的RootBeanDefinition并注册
2、如果corsConfigurations不为null,从context中获取名为mvcCorsConfigurations的BeanDefinition,将corsConfigurations作为参数添加到其中
3、返回名为mvcCorsConfigurations的RuntimeBeanReference
getConversionService(Element element, @Nullable Object source, ParserContext context)
private RuntimeBeanReference getConversionService(Element element, @Nullable Object source, ParserContext context) {
RuntimeBeanReference conversionServiceRef;
if (element.hasAttribute("conversion-service")) {
conversionServiceRef = new RuntimeBeanReference(element.getAttribute("conversion-service"));
}
else {
RootBeanDefinition conversionDef = new RootBeanDefinition(FormattingConversionServiceFactoryBean.class);
conversionDef.setSource(source);
conversionDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
String conversionName = context.getReaderContext().registerWithGeneratedName(conversionDef);
context.registerComponent(new BeanComponentDefinition(conversionDef, conversionName));
conversionServiceRef = new RuntimeBeanReference(conversionName);
}
return conversionServiceRef;
}
1、判断是否有conversion-service属性,若有则获取conversion-service,返回RuntimeBeanReference
2、构造类型为FormattingConversionServiceFactoryBean的RootBeanDefinition
getValidator(Element element, @Nullable Object source, ParserContext context)
private RuntimeBeanReference getValidator(Element element, @Nullable Object source, ParserContext context) {
if (element.hasAttribute("validator")) {
return new RuntimeBeanReference(element.getAttribute("validator"));
}
else if (javaxValidationPresent) {
RootBeanDefinition validatorDef = new RootBeanDefinition(
"org.springframework.validation.beanvalidation.OptionalValidatorFactoryBean");
validatorDef.setSource(source);
validatorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
String validatorName = context.getReaderContext().registerWithGeneratedName(validatorDef);
context.registerComponent(new BeanComponentDefinition(validatorDef, validatorName));
return new RuntimeBeanReference(validatorName);
}
else {
return null;
}
}
1、判断是否有validator属性,若有则获取validator,返回RuntimeBeanReference
2、如果javaxValidationPresent为true构造类型为org.springframework.validation.beanvalidation.OptionalValidatorFactoryBean的RootBeanDefinition
3、否则返回null
getMessageCodesResolver(Element element)
private RuntimeBeanReference getMessageCodesResolver(Element element) {
if (element.hasAttribute("message-codes-resolver")) {
return new RuntimeBeanReference(element.getAttribute("message-codes-resolver"));
}
else {
return null;
}
}
如果有message-codes-resolver,则获取该属性并返回RuntimeBeanReference,否则返回null。
getMessageConverters(Element element, @Nullable Object source, ParserContext context)
private ManagedList<?> getMessageConverters(Element element, @Nullable Object source, ParserContext context) {
Element convertersElement = DomUtils.getChildElementByTagName(element, "message-converters");
ManagedList<Object> messageConverters = new ManagedList<>();
if (convertersElement != null) {
messageConverters.setSource(source);
for (Element beanElement : DomUtils.getChildElementsByTagName(convertersElement, "bean", "ref")) {
Object object = context.getDelegate().parsePropertySubElement(beanElement, null);
messageConverters.add(object);
}
}
if (convertersElement == null || Boolean.parseBoolean(convertersElement.getAttribute("register-defaults"))) {
messageConverters.setSource(source);
messageConverters.add(createConverterDefinition(ByteArrayHttpMessageConverter.class, source));
RootBeanDefinition stringConverterDef = createConverterDefinition(StringHttpMessageConverter.class, source);
stringConverterDef.getPropertyValues().add("writeAcceptCharset", false);
messageConverters.add(stringConverterDef);
messageConverters.add(createConverterDefinition(ResourceHttpMessageConverter.class, source));
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));
}
if (jackson2XmlPresent) {
Class<?> type = MappingJackson2XmlHttpMessageConverter.class;
RootBeanDefinition jacksonConverterDef = createConverterDefinition(type, source);
GenericBeanDefinition jacksonFactoryDef = createObjectMapperFactoryDefinition(source);
jacksonFactoryDef.getPropertyValues().add("createXmlMapper", true);
jacksonConverterDef.getConstructorArgumentValues().addIndexedArgumentValue(0, jacksonFactoryDef);
messageConverters.add(jacksonConverterDef);
}
else if (jaxb2Present) {
messageConverters.add(createConverterDefinition(Jaxb2RootElementHttpMessageConverter.class, source));
}
if (jackson2Present) {
Class<?> type = MappingJackson2HttpMessageConverter.class;
RootBeanDefinition jacksonConverterDef = createConverterDefinition(type, source);
GenericBeanDefinition jacksonFactoryDef = createObjectMapperFactoryDefinition(source);
jacksonConverterDef.getConstructorArgumentValues().addIndexedArgumentValue(0, jacksonFactoryDef);
messageConverters.add(jacksonConverterDef);
}
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;
}
1、获取名为message-converters的Element
2、如果Element不为空,获取message-converters子标签下的bean或ref的元素解析后并添加到messageConverters集合中
3、如果convertersElement为null或者register-defaults属性为true,则
创建类型是ByteArrayHttpMessageConverter的RootBeanDefinition并添加到messageConverters集合
创建类型是StringHttpMessageConverter的RootBeanDefinition并添加到messageConverters集合
创建类型是ResourceHttpMessageConverter的RootBeanDefinition并添加到messageConverters集合
创建类型是ResourceRegionHttpMessageConverter的RootBeanDefinition并添加到messageConverters集合
创建类型是SourceHttpMessageConverter的RootBeanDefinition并添加到messageConverters集合
创建类型是AllEncompassingFormHttpMessageConverter的RootBeanDefinition并添加到messageConverters集合
如果romePresent为true,则创建类型是AtomFeedHttpMessageConverter,RssChannelHttpMessageConverter的RootBeanDefinition并添加到messageConverters集合
如果jackson2XmlPresent为true则创建类型是MappingJackson2XmlHttpMessageConverter(Jackson2ObjectMapperFactoryBean作为MappingJackson2XmlHttpMessageConverter参数)的RootBeanDefinition并添加到messageConverters集合
如果jaxb2Present为true,则创建类型是Jaxb2RootElementHttpMessageConverter的RootBeanDefinition并添加到messageConverters集合
如果jackson2Present为true,则创建类型是MappingJackson2HttpMessageConverter(Jackson2ObjectMapperFactoryBean作为参数)的RootBeanDefinition并添加到messageConverters集合
如果gsonPresent为true,则创建类型GsonHttpMessageConverter的RootBeanDefinition并添加到messageConverters集合
如果jackson2SmilePresent为true,则创建类型是MappingJackson2SmileHttpMessageConverter(Jackson2ObjectMapperFactoryBean作为参数)的RootBeanDefinition并添加到messageConverters集合
如果jackson2CborPresent为true,则创建类型是MappingJackson2CborHttpMessageConverter(Jackson2ObjectMapperFactoryBean作为参数)的RootBeanDefinition并添加到messageConverters集合
MessageConverter可参考https://blog.csdn.net/lianghecai52171314/article/details/106315408
MvcNamespaceUtils.registerDefaultComponents(ParserContext context, @Nullable Object source)
public static void registerDefaultComponents(ParserContext context, @Nullable Object source) {
registerBeanNameUrlHandlerMapping(context, source); // 创建类型是BeanNameUrlHandlerMapping的RootBeanDefinition
registerHttpRequestHandlerAdapter(context, source); // 创建类型是HttpRequestHandlerAdapter的RootBeanDefinition
registerSimpleControllerHandlerAdapter(context, source); // 创建类型是SimpleControllerHandlerAdapter的RootBeanDefinition
registerHandlerMappingIntrospector(context, source); // 创建类型是HandlerMappingIntrospector的RootBeanDefinition
registerLocaleResolver(context, source); //创建类型是AcceptHeaderLocaleResolver的RootBeanDefinition
registerThemeResolver(context, source); //创建类型是FixedThemeResolver的RootBeanDefinition
registerViewNameTranslator(context, source); //创建类型是DefaultRequestToViewNameTranslator的RootBeanDefinition
registerFlashMapManager(context, source); //创建类型是SessionFlashMapManager的RootBeanDefinition
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通