Spring Boot 中的 @ConditionalOnBean 注解详解

Spring Boot 中的 @ConditionalOnBean 注解详解

    • [1. 前言](#1. 前言)
    • [2. `@ConditionalOnBean` 作用与基本用法](#2. @ConditionalOnBean 作用与基本用法)
      • [2.1 `@ConditionalOnBean` 的作用](#2.1 @ConditionalOnBean 的作用)
      • [2.2 基本用法](#2.2 基本用法)
        • [示例:当 `DataSource` Bean 存在时,才创建 `MyService` Bean](#示例:当 DataSource Bean 存在时,才创建 MyService Bean)
    • [3. `@ConditionalOnBean` 详解](#3. @ConditionalOnBean 详解)
      • [3.1 `value` 和 `type` 属性(指定 Bean 类型)](#3.1 valuetype 属性(指定 Bean 类型))
      • [3.2 `name` 属性(指定 Bean 名称)](#3.2 name 属性(指定 Bean 名称))
      • [3.3 `annotation` 属性(指定 Bean 需要标注的注解)](#3.3 annotation 属性(指定 Bean 需要标注的注解))
      • [3.4 `search` 属性(搜索范围)](#3.4 search 属性(搜索范围))
    • [4. `@ConditionalOnBean` 使用场景](#4. @ConditionalOnBean 使用场景)
      • [场景 1:按需加载数据库相关 Bean](#场景 1:按需加载数据库相关 Bean)
      • [场景 2:启用某些自动配置](#场景 2:启用某些自动配置)
      • [场景 3:可选依赖的组件](#场景 3:可选依赖的组件)
    • [5. `@ConditionalOnBean` vs `@ConditionalOnMissingBean`](#5. @ConditionalOnBean vs @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 valuetype 属性(指定 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();
}

默认情况下,@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 吗?欢迎留言分享你的经验!🚀

相关推荐
用户6757049885026 分钟前
Redis 分布式锁的 5个坑,真的是又大又深!!
redis·后端
用户6757049885028 分钟前
Go 程序员进阶必读:这 24 个经典的 Golang 错误,连老手都会栽跟头!
后端·go
EntyIU9 分钟前
Java NIO 实战
java·开发语言·nio
用户693717500138410 分钟前
AI 领域的 Harness,到底是什么意思?
android·前端·后端
二宝哥10 分钟前
springboot项目使用Gradle工具实现依赖版本控制
java·spring boot·后端·gradle·版本
ITender25 分钟前
Nacos 迁移引发 Full GC 问题深度分析
后端·面试
Gatlin26 分钟前
逆向学习:我为什么放着文档不看,直接读字节码
后端
我不是外星人26 分钟前
一键还原任意网站,这套 Playwright + 多 Agent 工程流太猛了
前端·后端·ai编程
济*沧*海30 分钟前
Set集合深度解析:原理、特性与应用场景全攻略
java
geovindu31 分钟前
java: Singleton Pattern
java·开发语言·后端·单例模式·设计模式·创建型模式