问题说明

我们都知道,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 进行配置。

参考链接:ConditionalOnMissingBean失效问题追踪

SpringBoot 项目中配置多个 Jackson 的 ObjectMapper ,以及配置遇到的坑的更多相关文章

  1. SpringBoot12 QueryDSL01之QueryDSL介绍、springBoot项目中集成QueryDSL

    1 QueryDSL介绍 1.1 背景 QueryDSL的诞生解决了HQL查询类型安全方面的缺陷:HQL查询的扩展需要用字符串拼接的方式进行,这往往会导致代码的阅读困难:通过字符串对域类型和属性的不安 ...

  2. Spring-Boot项目中配置redis注解缓存

    Spring-Boot项目中配置redis注解缓存 在pom中添加redis缓存支持依赖 <dependency> <groupId>org.springframework.b ...

  3. springboot 项目中获取默认注入的序列化对象 ObjectMapper

    在 springboot 项目中使用 @SpringBootApplication 会自动标记 @EnableAutoConfiguration 在接口中经常需要使用时间类型,Date ,如果想要格式 ...

  4. 在SpringBoot项目中添加logback的MDC

    在SpringBoot项目中添加logback的MDC     先看下MDC是什么 Mapped Diagnostic Context,用于打LOG时跟踪一个“会话“.一个”事务“.举例,有一个web ...

  5. 解决springboot项目中@Value注解参数值为null的问题

    1.错误场景: springboot项目中在.properties文件(.yml)文件中配置了属性值,在Bean中使用@Value注解引入该属性,Bean的构造器中使用该属性进行初始化,此时有可能会出 ...

  6. 五分钟后,你将学会在SpringBoot项目中如何集成CAT调用链

    买买买结算系统 一年一度的双十一购物狂欢节就要到了,又到剁手党们开始表演的时刻了.当我们把种草很久的商品放入购物车以后,点击"结算"按钮时,就来到了买买买必不可少的结算页面了.让我 ...

  7. SpringBoot项目中遇到的BUG

    1.启动项目的时候报错 1.Error starting ApplicationContext. To display the auto-configuration report re-run you ...

  8. springboot项目中使用maven resources

    maven resource 组件可以把pom的变量替换到相关的resouces目录中的资源文件变量 示例项目:内容中心 (文章管理)  生成jar包,生成docker ,生成k8s文件 1.项目结构 ...

  9. 后端分页神器,mybatis pagehelper 在SSM与springboot项目中的使用

    mybatis pagehelper想必大家都耳熟能详了,是java后端用于做分页查询时一款非常好用的分页插件,同时也被人们称为mybatis三剑客之一,下面 就给大家讲讲如何在SSM项目和sprin ...

  10. 国际化的实现i18n--错误码国际化以及在springboot项目中使用

    国际化 ,英文叫 internationalization 单词太长 ,又被简称为 i18n(取头取尾中间有18个字母); 主要涉及3个类: Locale用来设置定制的语言和国家代码 Resource ...

随机推荐

  1. Dapr v1.9.0 版本已发布

    Dapr是一套开源.可移植的事件驱动型运行时,允许开发人员轻松立足云端与边缘位置运行弹性.微服务.无状态以及有状态等应用程序类型.Dapr能够确保开发人员专注于编写业务逻辑,而不必分神于解决分布式系统 ...

  2. Android 13 新特性及适配指南

    Android 13(API 33)于 2022年8月15日 正式发布(发布时间较往年早了一些),正式版Release源代码也于当日被推送到AOSP Android开源项目. 截止到笔者撰写这篇文章时 ...

  3. 如何用webgl(three.js)搭建一个3D库房,3D仓库,3D码头,3D集装箱可视化孪生系统——第十五课

    序 又是快两个月没写随笔了,长时间不总结项目,不锻炼文笔,一开篇,多少都会有些生疏,不知道如何开篇,如何写下去.有点江郎才尽,黔驴技穷的感觉. 写随笔,通常三步走,第一步,搭建框架,先把你要写的内容框 ...

  4. 分清国内版FireFox和国际版FireFox

    FireFox现在成为越来越多人替代Chrome的选择.但与Chrome不同的是,FireFox无论桌面端还是移动端,都有着『国际』和『国内』版本的区分. 二.正确的下载地址 2.1国内版的混淆视听: ...

  5. [苹果APP上架]ios App Store上架详细教程-一条龙顺滑上架-适合小白

    如何在 2022 年将您的应用提交到 App Store 您正在启动您的第一个应用程序,或者距离上次已经有一段时间了.作者纸飞机@cheng716051来给你讲讲将应用程序提交到 App Store ...

  6. 在Rocky8中安装VMware Workstation 的方法

    在Rocky8中安装VMware Workstation 的方法 1.Rocky必须是图形界面 2.下载wmware workstation(下载地址:https://www.vmware.com/i ...

  7. 解决“fast-forward, aborting”问题

    1. 现象 对某一个远程仓库 git pull 过程中,报错如下: # zl @ srv123 in ~/git/radxa/kernel [14:09:54] $ git pull remote: ...

  8. C++初阶(命名空间+缺省参数+const总结+引用总结+内联函数+auto关键字)

    命名空间 概述 在C/C++中,变量.函数和后面要学到的类都是大量存在的,这些变量.函数和类的名称将都存在于全局作用域中,可能会导致很多冲突.使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲 ...

  9. JAVA系列之类加载机制详解

    类的加载机制 ? 双亲委派机制 ? 什么是类加载器 ? 自定义类加载器有哪些应用场景 ? 通常,在关于Java的类加载部分会遇到以上疑问,本文将对类加载重要部分做详细介绍,包括重要的基础概念和应用场景 ...

  10. 软件开发-客观综合(GO)

    1 对从go源码和汇编源码生成可执行程序的过程,下面描述错误的是() ​A. 使用go tool compile可以将go源码编译成目标文件 B. 使用go tool asm可以将go源码编译成汇编代 ...