Spring Boot 中的 @ConditionalOnBean 注解详解
- 
- [1. 前言](#1. 前言)
 - [2. `@ConditionalOnBean` 作用与基本用法](#2. 
@ConditionalOnBean作用与基本用法) - 
- [2.1 `@ConditionalOnBean` 的作用](#2.1 
@ConditionalOnBean的作用) - [2.2 基本用法](#2.2 基本用法)
 - 
- [示例:当 `DataSource` Bean 存在时,才创建 `MyService` Bean](#示例:当 
DataSourceBean 存在时,才创建MyServiceBean) 
 - [示例:当 `DataSource` Bean 存在时,才创建 `MyService` Bean](#示例:当 
 
 - [2.1 `@ConditionalOnBean` 的作用](#2.1 
 - [3. `@ConditionalOnBean` 详解](#3. 
@ConditionalOnBean详解) - 
- [3.1 `value` 和 `type` 属性(指定 Bean 类型)](#3.1 
value和type属性(指定 Bean 类型)) - [3.2 `name` 属性(指定 Bean 名称)](#3.2 
name属性(指定 Bean 名称)) - [3.3 `annotation` 属性(指定 Bean 需要标注的注解)](#3.3 
annotation属性(指定 Bean 需要标注的注解)) - [3.4 `search` 属性(搜索范围)](#3.4 
search属性(搜索范围)) 
 - [3.1 `value` 和 `type` 属性(指定 Bean 类型)](#3.1 
 - [4. `@ConditionalOnBean` 使用场景](#4. 
@ConditionalOnBean使用场景) - 
- [场景 1:按需加载数据库相关 Bean](#场景 1:按需加载数据库相关 Bean)
 - [场景 2:启用某些自动配置](#场景 2:启用某些自动配置)
 - [场景 3:可选依赖的组件](#场景 3:可选依赖的组件)
 
 - [5. `@ConditionalOnBean` vs `@ConditionalOnMissingBean`](#5. 
@ConditionalOnBeanvs@ConditionalOnMissingBean) - [6. 结论](#6. 结论)
 
 
1. 前言
在 Spring Boot 中,条件注解(Conditional 注解) 是一种强大的功能,允许我们根据某些条件动态地注册或跳过特定的 Bean。其中,@ConditionalOnBean 是最常用的条件注解之一,它的作用是:当 Spring 容器中存在指定的 Bean 时,当前 Bean 才会被注册。
本篇文章将详细介绍 @ConditionalOnBean 的使用场景、原理,并提供多个示例帮助理解。
2. @ConditionalOnBean 作用与基本用法
2.1 @ConditionalOnBean 的作用
@ConditionalOnBean 主要用于以下场景:
- 按需加载 Bean:只有在某个 Bean 存在时,另一个 Bean 才会被创建。
 - 模块化设计 :某些功能模块需要依赖特定 Bean 才能启用,例如 仅当某个组件存在时,自动配置才会生效。
 - 避免 Bean 冲突 :如果某个 Bean 依赖其他 Bean,则可使用 
@ConditionalOnBean确保它不会因缺少依赖而加载失败。 
2.2 基本用法
示例:当 DataSource Bean 存在时,才创建 MyService Bean
        
            
            
              java
              
              
            
          
          import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
@Configuration
public class MyConfig {
    @Bean
    public DataSource dataSource() {
        // 这里模拟 DataSource 实例,实际可用 HikariDataSource、Druid 等
        return new FakeDataSource();
    }
    @Bean
    @ConditionalOnBean(DataSource.class)  // 仅当 DataSource 存在时,才创建 MyService
    public MyService myService() {
        return new MyService();
    }
}
class MyService {
    public MyService() {
        System.out.println("MyService 被创建");
    }
}
class FakeDataSource implements DataSource {
    // 这里可以模拟 DataSource 方法
}
        执行结果:
MyService 被创建
        如果 dataSource() 方法被注释掉,则 MyService 不会被创建。
3. @ConditionalOnBean 详解
@ConditionalOnBean 提供了多个属性,可以更加灵活地控制 Bean 的创建。
3.1 value 和 type 属性(指定 Bean 类型)
用于指定某种类型的 Bean 存在时,当前 Bean 才会被注册。
            
            
              java
              
              
            
          
          @Bean
@ConditionalOnBean(value = DataSource.class)  // 仅当 DataSource 存在时生效
public MyRepository myRepository() {
    return new MyRepository();
}
        等效于:
            
            
              java
              
              
            
          
          @Bean
@ConditionalOnBean(type = "javax.sql.DataSource")  // 使用全限定类名
public MyRepository myRepository() {
    return new MyRepository();
}
        区别:
value:直接使用 Class 类型,编译时检查更安全。type:使用字符串,可用于避免某些类找不到(如可选依赖)。
3.2 name 属性(指定 Bean 名称)
用于 指定某个 Bean 名称是否存在 来决定当前 Bean 是否加载。
            
            
              java
              
              
            
          
          @Bean
@ConditionalOnBean(name = "customBean")  // 仅当名为 customBean 的 Bean 存在时注册
public MyComponent myComponent() {
    return new MyComponent();
}
        3.3 annotation 属性(指定 Bean 需要标注的注解)
可以指定某些 Bean 是否包含特定注解,如果包含,则当前 Bean 才会被注册。
            
            
              java
              
              
            
          
          @Bean
@ConditionalOnBean(annotation = Repository.class)  // 仅当存在 @Repository 注解的 Bean 时生效
public MyService myService() {
    return new MyService();
}
        3.4 search 属性(搜索范围)
默认情况下,@ConditionalOnBean 只会在 当前应用上下文 中查找 Bean,而不会查找 父上下文 (即 Spring Boot 的 ApplicationContext 层级)。
search 选项可以指定搜索范围:
ALL:在所有父子ApplicationContext中搜索。CURRENT(默认):仅搜索当前ApplicationContext。
            
            
              java
              
              
            
          
          @Bean
@ConditionalOnBean(value = DataSource.class, search = SearchStrategy.ALL) // 在所有上下文中搜索
public MyService myService() {
    return new MyService();
}
        4. @ConditionalOnBean 使用场景
场景 1:按需加载数据库相关 Bean
如果应用程序中 使用了数据库 ,则提供一个 DatabaseService,否则不创建:
            
            
              java
              
              
            
          
          @Bean
@ConditionalOnBean(DataSource.class)
public DatabaseService databaseService() {
    return new DatabaseService();
}
        场景 2:启用某些自动配置
Spring Boot 的 spring-boot-autoconfigure 模块大量使用 @ConditionalOnBean 来控制自动配置。例如:
- 只有当 
DispatcherServlet存在时,Spring MVC 相关的自动配置才会生效。 
            
            
              java
              
              
            
          
          @Configuration
@ConditionalOnBean(DispatcherServlet.class)
public class MvcAutoConfiguration {
    // 仅当 DispatcherServlet 存在时,Spring MVC 配置生效
}
        场景 3:可选依赖的组件
有时,某些功能是可选的,比如当 Redis 组件存在时,才创建缓存管理器:
            
            
              java
              
              
            
          
          @Bean
@ConditionalOnBean(name = "redisTemplate")  // 只有当 redisTemplate 存在时才加载
public CacheManager cacheManager() {
    return new RedisCacheManager();
}
        5. @ConditionalOnBean vs @ConditionalOnMissingBean
| 注解 | 作用 | 
|---|---|
@ConditionalOnBean | 
当指定 Bean 存在时,才注册当前 Bean | 
@ConditionalOnMissingBean | 
当指定 Bean 不存在时,才注册当前 Bean | 
示例:
            
            
              java
              
              
            
          
          @Bean
@ConditionalOnMissingBean(DataSource.class)  // 仅当 DataSource 不存在时才创建
public DataSource defaultDataSource() {
    return new DefaultDataSource();
}
        6. 结论
在 Spring Boot 中,@ConditionalOnBean 可以帮助我们根据 是否存在特定 Bean 来 动态注册 Bean ,广泛用于 按需加载、自动配置 等场景。
总结:
✅ 指定 Bean 类型 :@ConditionalOnBean(DataSource.class)
✅ 指定 Bean 名称 :@ConditionalOnBean(name = "customBean")
✅ 指定 Bean 注解 :@ConditionalOnBean(annotation = Repository.class)
✅ 搜索范围 :@ConditionalOnBean(search = SearchStrategy.ALL)
你在项目中用过 @ConditionalOnBean 吗?欢迎留言分享你的经验!🚀