問題說明
我們都知道,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;
}
}
原因排查分析
通過修改代碼進行測試
- 将配置檔案第一個删除掉,測試發現,隻注入了一個名稱為 snakeCaseObjectMapper 的 bean;
- 注釋掉注解 @ConditionalOnMissingBean,測試發現,兩個 bean 都注入成功;
- 将 @ConditionalOnMissingBean 放在第二個 bean 上,測試發現,隻注入了第一個 bean;
- 将配置的兩個 bean 調換上下順序,測試發現,隻注入了第一個 bean;
- 将配置檔案第一個删除掉,并将 @ConditionalOnMissingBean 放在第二個 bean 上,測試發現,隻注入了第二個 bean。
問題答案:
第一個問題,雖然第一個 bean 和自動配置中的一樣,但是由于自定義配置和自動配置檔案加載順序的原因,就會産生不同的結果,是以是不能删除的。
第二個問題,@ConditionalOnMissingBean 其實可以省略,如果調用兩個 bean 的上下順序,這個就注入不成功,因為同一個配置檔案中,如果沒有依賴關系,則按照上下順序進行加載的。
結論總結
- 同一個配置檔案中,如果多個 bean 沒有依賴關系,則按照上下順序進行加載。
- Spring Boot 的自動配置均是通過 spring.factories 來指定的,它的優先級最低(執行時機是最晚的);通過掃描進來的(也就是項目組自定義配置類)優先級是最高的。
- 自動配置順序相關的三大注解 @AutoConfigureBefore、@AutoConfigureAfter、@AutoConfigureOrder 隻能作用于自動配置類,不能作用于被啟動類掃描的配置類中。
Jackson 自動裝配分析
- 在這個 JacksonAutoConfiguration 類裡面會生成一個 Primary 的 ObjectMapper 的 bean,注入 ObjectMapper 的 bean 時,依賴了 Jackson2ObjectMapperBuilder 的 bean;
- 找到注入 Jackson2ObjectMapperBuilder 的 bean,發現其依賴 List,具體操作就是把容器裡面的所有的 Jackson2ObjectMapperBuilderCustomizer 拿出來,對 Jackson2ObjectMapperBuilder 進行設定;Jackson2ObjectMapperBuilderCustomizer 接口隻有一個方法,其實就是 Jackson2ObjectMapperBuilder 提供的回調鈎子方法;
- 是以,如果要對 ObjectMapper 做自定義配置化操作,要麼實作 Jackson2ObjectMapperBuilderCustomizer 接口并注入這個實作的 bean,要麼直接使用 Jackson2ObjectMapperBuilder 進行配置。
原文連結:https://www.cnblogs.com/dxiaodang/p/17049168.html