天天看點

SpringBoot 項目配置多個 Jackson 的 ObjectMapper ,及配置遇到的坑

作者:Java牛逼架構師
SpringBoot 項目配置多個 Jackson 的 ObjectMapper ,及配置遇到的坑

問題說明

我們都知道,SpringBoot 項目中,如果引入了 Jackson 的包,哪怕不配置,SpringBoot 也會幫我們配置(JacksonAutoConfiguration)。

由于我的項目中需要使用多個不同的配置參數的 ObjectMapper,我同僚直接配置了兩個@Bean,并且其中一個使用@ConditionalOnMissingBean 和@Primary 标注,但是奇怪的是,居然兩個 Bean 都注入成功了,瞬間對這塊邏輯産生了懷疑,本着探索的精神,進行分析!

  • 問題 1:自定義配置檔案中第一個注入的 Bean 和 JacksonAutoConfiguration 一模一樣,為啥還需要重新寫一遍,是否把第一個删除了?
  • 問題 2:@ConditionalOnMissingBean 不應該是缺少該對象執行個體才會注入,否則不注入嘛?
@Configuration
public class JacksonConfig {

    @Bean
    @Primary
    @ConditionalOnMissingBean
    public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
        return builder.createXmlMapper(false).build();
    }

    @Bean("snakeCaseObjectMapper")
    public ObjectMapper snakeCaseObjectMapper() {
        ObjectMapper result = new ObjectMapper();
        result.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
        result.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

        // java8日期日期處理
        JacksonUtil.setDateTimeSerializer(result);

        return result;
    }
}
           

原因排查分析

通過修改代碼進行測試

  1. 将配置檔案第一個删除掉,測試發現,隻注入了一個名稱為 snakeCaseObjectMapper 的 bean;
  2. 注釋掉注解 @ConditionalOnMissingBean,測試發現,兩個 bean 都注入成功;
  3. 将 @ConditionalOnMissingBean 放在第二個 bean 上,測試發現,隻注入了第一個 bean;
  4. 将配置的兩個 bean 調換上下順序,測試發現,隻注入了第一個 bean;
  5. 将配置檔案第一個删除掉,并将 @ConditionalOnMissingBean 放在第二個 bean 上,測試發現,隻注入了第二個 bean。

問題答案:

第一個問題,雖然第一個 bean 和自動配置中的一樣,但是由于自定義配置和自動配置檔案加載順序的原因,就會産生不同的結果,是以是不能删除的。

第二個問題,@ConditionalOnMissingBean 其實可以省略,如果調用兩個 bean 的上下順序,這個就注入不成功,因為同一個配置檔案中,如果沒有依賴關系,則按照上下順序進行加載的。

結論總結

  • 同一個配置檔案中,如果多個 bean 沒有依賴關系,則按照上下順序進行加載。
  • Spring Boot 的自動配置均是通過 spring.factories 來指定的,它的優先級最低(執行時機是最晚的);通過掃描進來的(也就是項目組自定義配置類)優先級是最高的。
  • 自動配置順序相關的三大注解 @AutoConfigureBefore、@AutoConfigureAfter、@AutoConfigureOrder 隻能作用于自動配置類,不能作用于被啟動類掃描的配置類中。

Jackson 自動裝配分析

  1. 在這個 JacksonAutoConfiguration 類裡面會生成一個 Primary 的 ObjectMapper 的 bean,注入 ObjectMapper 的 bean 時,依賴了 Jackson2ObjectMapperBuilder 的 bean;
  2. 找到注入 Jackson2ObjectMapperBuilder 的 bean,發現其依賴 List,具體操作就是把容器裡面的所有的 Jackson2ObjectMapperBuilderCustomizer 拿出來,對 Jackson2ObjectMapperBuilder 進行設定;Jackson2ObjectMapperBuilderCustomizer 接口隻有一個方法,其實就是 Jackson2ObjectMapperBuilder 提供的回調鈎子方法;
  3. 是以,如果要對 ObjectMapper 做自定義配置化操作,要麼實作 Jackson2ObjectMapperBuilderCustomizer 接口并注入這個實作的 bean,要麼直接使用 Jackson2ObjectMapperBuilder 進行配置。
原文連結:https://www.cnblogs.com/dxiaodang/p/17049168.html

繼續閱讀