目錄
一、加載轉換器的流程,通過下面詳細的時序圖可知

原圖見百度雲
二、自定義轉換器的加載邏輯
1、總共有三種方式
a、@bean;
b、實現WebMvcConfigurer類的方法configureMessageConverters 或者 extendMessageConverters方法;
c、
如果b和c同時定義,只會生效c的方式;
下面講講a、b同時使用和 a、c同時使用的優先級區別
2、a 和 c同時使用
-
-
繼承WebMvcConfigurationSupport類,覆蓋方法configureMessageConverters
-
如下圖:

結論:這種方法,只會有JavaSerializationConverter1、JavaSerializationConverter2兩個轉換器在處理json請求時生效,並且JavaSerializationConverter2在JavaSerializationConverter1前面。
加載流程如下:

調用棧如下:
preInstantiateSingletons:737, DefaultListableBeanFactory (org.springframework.beans.factory.support)
finishBeanFactoryInitialization:867, AbstractApplicationContext (org.springframework.context.support)
refresh:548, AbstractApplicationContext (org.springframework.context.support)
最后會調用org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons

在圖①中,遍歷500多個bean,進行非延遲加載的bean創建,這里會先創建我們自定義的轉換器JavaSerializationConverter,然后會創建requestMappingHandlerAdapter
創建requestMappingHandlerAdapter的過程:
這個對象是由org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#requestMappingHandlerAdapter這個bean實例化方法創建的,因為我們自定義MyConverterConfig2繼承了WebMvcConfigurationSupport對象,所以這一系列方法實際是自定義對象觸發的如圖:

圖中①會給org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#messageConverters屬性賦值四個默認轉換器如下:

賦值后回到上面圖②:會調用MyConverterConfig2的父類WebMvcConfigurationSupport#getMessageConverters的方法,如下:

②執行MyConverterConfig2#configureMessageConverters方法加入一個轉換器;
③這時WebMvcConfigurationSupport#messageConverters屬性不為空;
④不會執行,也就不會記載spring默認八個轉換器;
⑤執行MyConverterConfig2#extendMessageConverters方法加入一個轉換器;
方法退出后,WebMvcConfigurationSupport#messageConverters就有兩個我們自定義的轉換器:
①中會調用RequestMappingHandlerAdapter#getDefaultArgumentResolvers獲取一系列默認參數解析器列表:
創建過程細化流程見第一個標題畫的時序圖,這里不詳細列出,大概流程如下:
如下圖:

①中匿名創建了WebMvcConfigurationSupport的子類,添加了defaultMessageConverters方法,改子類沒有重寫父類任何方法;
這個時候因為是匿名創建的子類,沒有給父類任何屬性賦值,也就意味着圖中:
②是空方法;
③這時屬性還是空的;
④這里會獲取spirng的八個默認轉換器;
⑤是空方法;
-
- spring 八個轉換器和springboot 默認三個轉換器組合,並賦值給HttpMessageConverters#converters(這個對象在springboot包中,也就是springboot的轉換器所屬對象),並沒有賦值給WebMvcConfigurationSupport#messageConverters,所以WebMvcConfigurationSupport#messageConverters(這個對象在spring包中,也就是spring中生效的還是我們自定義的兩個轉換器)中還是上面我們自定義類MyConverterConfig2中方法添加的兩個轉換器;
3、a 和 b同時使用
-
-
實現WebMvcConfigurer類的方法configureMessageConverters
添加到list末尾converters.add(new JavaSerializationConverter());
-
實現WebMvcConfigurer類的方法extendMessageConverters

如下圖:
-
前面流程和之前一樣,只不過創建RequestMappingHandlerAdapter的對象不再是自定義的(WebMvcConfigurationSupport的子類MyConverterConfig2),而是spring自己的WebMvcConfigurationSupport對象,所以調用WebMvcConfigurationSupport#getMessageConverters
②執行WebMvcConfigurationSupport#configureMessageConverters方法,
這里會遍歷三個WebMvcConfigurer,包括我們自定義的MyConverterConfig也實現了WebMvcConfigurer接口,如下:

先去遍歷springboot自動配置,也就是會創建HttpMessageConverters,跟之前一樣,如下圖:

-
獲得spring八個默認轉換器,排序,xml轉換器放最后;
-
-
④不會執行,也就不會再次加載spring默認八個轉換器;



跟之前一樣,不過是方法名改為了extendMessageConverters,繼續遍歷WebMvcConfigurer,包括我們自定義的MyConverterConfig,如下:

當遍歷到我們自定義類的時候MyConverterConfig#extendMessageConverters,會添加自定義轉換器JavaSerializationConverter2,這時有13個轉換器了:

繼續遍歷第三個SpringDataWebConfiguration的時候,源碼如下:
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) { if (ClassUtils.isPresent("com.jayway.jsonpath.DocumentContext", this.context.getClassLoader()) && ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", this.context.getClassLoader())) { // 如果存在DocumentContext和ObjectMapper類型 ObjectMapper mapper = (ObjectMapper)getUniqueBean(ObjectMapper.class, this.context, ObjectMapper::new); ProjectingJackson2HttpMessageConverter converter = new ProjectingJackson2HttpMessageConverter(mapper); converter.setBeanFactory(this.context); this.forwardBeanClassLoader(converter); // ProjectingJackson2HttpMessageConverter加入到轉換器第一位 converters.add(0, converter); } if (ClassUtils.isPresent("org.xmlbeam.XBProjector", this.context.getClassLoader())) { converters.add(0, this.xmlBeamHttpMessageConverter.orElseGet(() -> { return new XmlBeamHttpMessageConverter(); })); } }
從這里可以看出只要存在DocumentContext和ObjectMapper類型,就會將ProjectingJackson2HttpMessageConverter加入到轉換器第一位加入到轉換器列表第一位,而ProjectingJackson2HttpMessageConverter從創建的邏輯來看是支持json格式的,如下:
所以目前轉換器列表第一位是ProjectingJackson2HttpMessageConverter,也就是spring默認采用的jackson的json轉換器,轉換器列表此時如下:

RequestMappingHandlerAdapter#messageConverters也會賦值這14個轉換器
之后會執行RequestMappingHandlerAdapter#afterPropertiesSet初始化方法,進而會將14個轉換器賦值給









