问题说明
由于我的项目中需要使用多个不同的配置参数的 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 和自动配置中的一样,但是由于自定义配置和自动配置文件加载顺序的原因,就会产生不同的结果,所以是不能删除的。
结论总结
-
自动配置顺序相关的三大注解 @AutoConfigureBefore、@AutoConfigureAfter、@AutoConfigureOrder 只能作用于自动配置类,不能作用于被启动类扫描的配置类中。
同一个配置文件中,如果多个 bean 没有依赖关系,则按照上下顺序进行加载。
Jackson 自动装配分析
-
找到注入 Jackson2ObjectMapperBuilder 的 bean,发现其依赖 List
,具体操作就是把容器里面的所有的 Jackson2ObjectMapperBuilderCustomizer 拿出来,对 Jackson2ObjectMapperBuilder 进行设置;Jackson2ObjectMapperBuilderCustomizer 接口只有一个方法,其实就是 Jackson2ObjectMapperBuilder 提供的回调钩子方法;