@ConditionalOnBean 就是它们的反面镜:“只有当某个特定的 Bean 已经存在于容器中时,我才会被实例化。”
这通常用于依赖性配置。例如:只有当你配置了“数据库连接池(DataSource)”,我才去加载“事务管理器(TransactionManager)”。
1. 核心逻辑
它的判断标准是:“容器里有没有那个谁?有的话,我也加入;没有的话,我也消失。”
2. 为什么要用它?
强依赖关系:某些功能必须建立在另一个功能存在的基础上。
避免异常:如果依赖的 Bean 不存在,直接创建当前 Bean 可能会导致空指针或启动报错。通过这个注解,Spring 会优雅地跳过这个 Bean 的创建。
插件式开发:当用户引入了某个可选的 SDK(比如 Redis),你的组件才自动激活相关的缓存功能。
3. 语法与参数
@Bean
@ConditionalOnBean(DataSource.class)
public MyDatabaseHelper myHelper(DataSource ds) {
return new MyDatabaseHelper(ds);
}
value / type: 检查是否存在指定类型的 Bean(最常用)。
name: 检查是否存在指定名称(ID)的 Bean。
annotation: 检查是否有 Bean 标注了特定的注解。
4. 实战:联动配置
假设你正在写一个监控系统,只有当用户定义了 MeterRegistry(用于指标收集)时,你才开启“自动上报数据”的功能。
@Configuration
public class MetricsAutoConfiguration {
// 只有当容器里已经有 MeterRegistry 这个 Bean 了,
// 才会创建 MetricsReporter
@Bean
@ConditionalOnBean(MeterRegistry.class)
public MetricsReporter metricsReporter(MeterRegistry registry) {
return new MetricsReporter(registry);
}
}
5. ⚠️ 最关键的注意事项:加载顺序
这是 @ConditionalOnBean 最容易让人掉头发的地方。
Bean 的扫描是有顺序的。 如果 Spring 扫描到 @ConditionalOnBean(A.class) 时,A 还没有被定义(虽然它可能在后面的配置类里),Spring 也会判定为“不存在”,从而跳过当前 Bean。
黄金法则:
尽量在自动配置类(Auto-configuration)中使用:官方建议将其用于外部库的自动配置,因为 Spring Boot 会在所有用户定义的
@Component加载完后,才去处理这些自动配置。
配合 @AutoConfigureAfter 使用:如果你明确知道依赖哪个配置类,可以用这个注解强制规定先后顺序。
@Configuration
@AutoConfigureAfter(DataSourceAutoConfiguration.class) // 确保在数据源配置完后再动
public class MyJdbcConfig {
@Bean
@ConditionalOnBean(DataSource.class)
public MyTool myTool() { ... }
}
6. 三大注解对比表
这三个注解基本涵盖了 Spring Boot 自动配置 90% 的场景。
评论