Spring Boot 中的 @ConditionalOnBean 注解详解

打印 上一主题 下一主题

主题 991|帖子 991|积分 2973

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

  1. import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
  2. import org.springframework.context.annotation.Bean;
  3. import org.springframework.context.annotation.Configuration;
  4. import javax.sql.DataSource;
  5. @Configuration
  6. public class MyConfig {
  7.     @Bean
  8.     public DataSource dataSource() {
  9.         // 这里模拟 DataSource 实例,实际可用 HikariDataSource、Druid 等
  10.         return new FakeDataSource();
  11.     }
  12.     @Bean
  13.     @ConditionalOnBean(DataSource.class)  // 仅当 DataSource 存在时,才创建 MyService
  14.     public MyService myService() {
  15.         return new MyService();
  16.     }
  17. }
  18. class MyService {
  19.     public MyService() {
  20.         System.out.println("MyService 被创建
  21. ");
  22.     }
  23. }
  24. class FakeDataSource implements DataSource {
  25.     // 这里可以模拟 DataSource 方法
  26. }
复制代码
执行效果
  1. MyService 被创建
复制代码
如果 dataSource() 方法被解释掉,则 MyService 不会被创建。

3. @ConditionalOnBean 详解

@ConditionalOnBean 提供了多个属性,可以更加灵活地控制 Bean 的创建。
3.1 value 和 type 属性(指定 Bean 范例)

用于指定某种范例的 Bean 存在时,当前 Bean 才会被注册。
  1. @Bean
  2. @ConditionalOnBean(value = DataSource.class)  // 仅当 DataSource 存在时生效
  3. public MyRepository myRepository() {
  4.     return new MyRepository();
  5. }
复制代码
等效于:
  1. @Bean
  2. @ConditionalOnBean(type = "javax.sql.DataSource")  // 使用全限定类名
  3. public MyRepository myRepository() {
  4.     return new MyRepository();
  5. }
复制代码
区别


  • value:直接使用 Class 范例,编译时检查更安全。
  • type:使用字符串,可用于避免某些类找不到(如可选依赖)。

3.2 name 属性(指定 Bean 名称)

用于 指定某个 Bean 名称是否存在 来决定当前 Bean 是否加载。
  1. @Bean
  2. @ConditionalOnBean(name = "customBean")  // 仅当名为 customBean 的 Bean 存在时注册
  3. public MyComponent myComponent() {
  4.     return new MyComponent();
  5. }
复制代码

3.3 annotation 属性(指定 Bean 需要标注的注解)

可以指定某些 Bean 是否包罗特定注解,如果包罗,则当前 Bean 才会被注册。
  1. @Bean
  2. @ConditionalOnBean(annotation = Repository.class)  // 仅当存在 @Repository 注解的 Bean 时生效
  3. public MyService myService() {
  4.     return new MyService();
  5. }
复制代码

3.4 search 属性(搜刮范围)

默认情况下,@ConditionalOnBean 只会在 当前应用上下文 中查找 Bean,而不会查找 父上下文(即 Spring Boot 的 ApplicationContext 层级)。
search 选项可以指定搜刮范围:


  • ALL:在全部父子 ApplicationContext 中搜刮。
  • CURRENT(默认):仅搜刮当前 ApplicationContext。
  1. @Bean
  2. @ConditionalOnBean(value = DataSource.class, search = SearchStrategy.ALL) // 在所有上下文中搜索
  3. public MyService myService() {
  4.     return new MyService();
  5. }
复制代码

4. @ConditionalOnBean 使用场景

场景 1:按需加载数据库相干 Bean

如果应用程序中 使用了数据库,则提供一个 DatabaseService,否则不创建:
  1. @Bean
  2. @ConditionalOnBean(DataSource.class)
  3. public DatabaseService databaseService() {
  4.     return new DatabaseService();
  5. }
复制代码

场景 2:启用某些自动配置

Spring Boot 的 spring-boot-autoconfigure 模块大量使用 @ConditionalOnBean 来控制自动配置。比方:


  • 只有当 DispatcherServlet 存在时,Spring MVC 相干的自动配置才会生效
  1. @Configuration
  2. @ConditionalOnBean(DispatcherServlet.class)
  3. public class MvcAutoConfiguration {
  4.     // 仅当 DispatcherServlet 存在时,Spring MVC 配置生效
  5. }
复制代码

场景 3:可选依赖的组件

偶然,某些功能是可选的,好比当 Redis 组件存在时,才创建缓存管理器:
  1. @Bean
  2. @ConditionalOnBean(name = "redisTemplate")  // 只有当 redisTemplate 存在时才加载
  3. public CacheManager cacheManager() {
  4.     return new RedisCacheManager();
  5. }
复制代码

5. @ConditionalOnBean vs @ConditionalOnMissingBean

注解作用@ConditionalOnBean当指定 Bean 存在时,才注册当前 Bean@ConditionalOnMissingBean当指定 Bean 不存在时,才注册当前 Bean 示例:
  1. @Bean
  2. @ConditionalOnMissingBean(DataSource.class)  // 仅当 DataSource 不存在时才创建
  3. public DataSource defaultDataSource() {
  4.     return new DefaultDataSource();
  5. }
复制代码

6. 结论

在 Spring Boot 中,@ConditionalOnBean 可以帮助我们根据 是否存在特定 Bean动态注册 Bean,广泛用于 按需加载、自动配置 等场景。
总结:

指定 Bean 范例:@ConditionalOnBean(DataSource.class)
指定 Bean 名称:@ConditionalOnBean(name = "customBean")
指定 Bean 注解:@ConditionalOnBean(annotation = Repository.class)
搜刮范围:@ConditionalOnBean(search = SearchStrategy.ALL)
你在项目中用过 @ConditionalOnBean 吗?接待留言分享你的经验!
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

商道如狼道

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表