应使用@ConditionalOnMissingBean的value属性指定Class类型来精确控制Bean注册。它检查容器中是否存在指定类型或其子类/实现类的Bean;name属性按名称精确匹配,优先级高于类型;type属性用字符串类名,编译期无依赖但运行时有风险;多类型需全部缺失才生效。

在 Spring Boot 自动配置中,需要精确控制某个 Bean 仅在容器中尚未存在同类型实例时才注册,这时必须明确指定 @ConditionalOnMissingBean 的匹配类型,否则可能因类型推断失败导致条件失效或覆盖异常。
通过 value 属性指定 Class 类型
这是最常用、最推荐的方式。@ConditionalOnMissingBean 会检查容器中是否存在 【与 value 中指定 Class 兼容的 Bean】(包括子类、实现类)。
在 @Bean 方法上直接写:
@Bean
@ConditionalOnMissingBean(value = DataSource.class)
public DataSource dataSource() {
return new HikariDataSource();
}
Spring 启动时会扫描所有已注册的 Bean 定义,只要发现任意一个 Bean 的类型是 DataSource 或其子类型(如 HikariDataSource、BasicDataSource),该条件即不成立,方法不会执行。
通过 name 属性按 Bean 名称精确匹配
当需要绕过类型继承关系、只看 Bean 的注册名称时使用。它不关心类型是否兼容,只查 ApplicationContext.getBeanNamesForType() 之外的显式命名注册。
方法一:指定单一 Bean 名称
@Bean
@ConditionalOnMissingBean(name = "customDataSource")
public DataSource fallbackDataSource() { ... }
注意:如果用户定义了 @Bean(name = "customDataSource") DataSource ds,哪怕类型是 XADataSource,这个条件也会失效——【name 匹配优先级高于类型匹配】。
方法二:指定多个名称(用数组)
@ConditionalOnMissingBean(name = {"primaryDs", "backupDs"})
同时指定 value 和 name 实现双重约束
只有当容器中既没有指定类型的 Bean,也没有指定名称的 Bean 时,条件才成立。这种写法极少用,但能规避某些边缘冲突。
@Bean
@ConditionalOnMissingBean(value = SmsSender.class, name = "defaultSmsSender")
public SmsSender smsSender() { ... }
此时若存在类型为 SmsSender 的 bean 但名字叫 "aliyunSms",或名字为 "defaultSmsSender" 但类型是 String,则条件仍成立。
用 type 属性替代 value 指定字符串类名
第一步:在注解中传入全限定类名字符串
@ConditionalOnMissingBean(type = "com.example.service.UserService")
第二步:确保该类在 classpath 中可加载,否则启动时报 ClassNotFoundException;若类不存在,条件自动视为“缺失”,Bean 会被创建——这容易引发误判。
第三步:type 和 value 互斥,不能同时出现。type 的优势在于编译期不依赖该类(适合模块化场景),但运行时风险更高。
匹配多个不同类型
第一步:列出所有需同时检查的 Class
@ConditionalOnMissingBean({DataSource.class, XADataSource.class})
第二步:条件成立要求——容器中 【所有列出的类型都完全不存在】。只要有一个存在(比如 DataSource 存在而 XADataSource 不存在),整个条件即失败,Bean 不会被创建。
第三步:适用于提供统一抽象层的默认实现,例如嵌入式数据库配置同时覆盖 JDBC 和分布式事务数据源。

















