Spring IoC 如何实现条件化装配 Bean?

Spring 条件化Bean装配:深入理解 @Conditional 注解 在本文中,我们将深入探讨Spring中的条件化Bean装配机制,重点介绍其中的关键概念和技术。我们将从介绍条件化Bean的基本概念和使用场景开始,逐步深入到@Conditional注解的原理和用法,以及如何自定义条件、组合条件、扩展条件注解等方面。通过本文的学习,读者将能够全面了解Spring中条件化Bean装配的原理和实践,从而更好地应用于自己的项目中,并加深对Spring框架核心功能的理解和应用。 阅读详情

条件化装配 Bean(Conditional Bean Assembly) 指的是:让 Spring 容器根据特定的条件来决定是否要创建和注册某一个 Bean。

这就像一个智能工厂的生产线,可以根据客户的订单(条件)来决定是安装汽油引擎还是电动机。这个机制是 Spring Boot 自动配置(Auto-configuration)的基石。


核心武器:@Conditional 注解

所有条件化装配都源于 Spring 4.0 引入的 @Conditional 注解。它是一个元注解,意思是它可以被用在其他注解上。

它的工作原理是:
@Conditional 注解需要一个 Condition 接口的实现类。在这个实现类中,你可以编写任意逻辑来判断条件是否满足。如果满足(返回 true),则被注解的 Bean 会被创建;如果不满足(返回 false),则被忽略。

// 这是一个自定义的条件
public class MyCustomCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        // 在这里编写你的判断逻辑
        // 比如,检查某个环境变量是否存在
        return System.getenv("MY_APP_MODE") != null;
    }
}

// 在配置类或Bean方法上使用
@Configuration
@Conditional(MyCustomCondition.class) // <-- 只有当条件满足时,这个配置类及其所有Bean才生效
public class MySpecialConfiguration {
    @Bean
    public MyService myService() {
        return new MyService();
    }
}

虽然 @Conditional 很强大,但每次都自己写一个 Condition 类比较繁琐。因此,Spring Boot 在此基础上,提供了一套开箱即用的、更具体的条件注解,覆盖了 99% 的日常场景。


Spring Boot 提供的常用条件注解

这些注解通常用在 @Bean 方法上或 @Configuration 类上。

1. @ConditionalOnProperty (最常用)

条件:当配置文件(application.properties 或 application.yml)中某个属性的值满足指定条件时。

场景:通过一个配置项来控制某个功能的开启或关闭。

// application.properties
// a. 开启短信通知
notification.service.type=sms 
// b. 开启某个高级功能
feature.x.enabled=true
// 只有当 notification.service.type 的值是 "sms" 时,才创建 SmsService 这个 Bean
@Bean
@ConditionalOnProperty(name = "notification.service.type", havingValue = "sms")
public NotificationService smsService() {
    return new SmsService();
}

// 只有当 feature.x.enabled 的值是 "true" 时,才创建 FeatureX Bean
// matchIfMissing = true 表示如果配置文件里根本没写这个属性,也算作条件满足(即默认开启)
@Bean
@ConditionalOnProperty(name = "feature.x.enabled", havingValue = "true", matchIfMissing = true)
public FeatureX featureX() {
    return new FeatureX();
}
2. @ConditionalOnBean 和 @ConditionalOnMissingBean

条件:当 IoC 容器中存在(或不存在)某个类型的 Bean 时。

这是实现“默认实现”和“用户可覆盖”模式的利器。

场景:你提供一个默认的缓存实现(如内存缓存),但允许用户自己定义一个 Redis 缓存 Bean 来覆盖它。

@Configuration
public class CacheAutoConfiguration {

    // **关键**:只有当容器中不存在任何 CacheService 类型的 Bean 时,
    // 才创建下面这个默认的 InMemoryCacheService。
    @Bean
    @ConditionalOnMissingBean(CacheService.class)
    public CacheService inMemoryCache() {
        System.out.println("No custom cache found. Creating default InMemoryCache.");
        return new InMemoryCacheService();
    }
}

// 在用户的配置中:
// 如果用户自己定义了下面这个 Bean...
// @Configuration
// public class MyCacheConfig {
//     @Bean
//     public CacheService redisCache() {
//         return new RedisCacheService(); // 用户自定义的实现
//     }
// }
// ...那么上面的 InMemoryCacheService 就不会被创建。

@ConditionalOnBean 则相反,表示只有当容器中已经存在某个 Bean 时,才创建当前 Bean。这常用于配置依赖于其他组件的 Bean。

3. @ConditionalOnClass 和 @ConditionalOnMissingClass

条件:当应用的 classpath 中存在(或不存在)某个类时。

这是编写 starter 模块的核心。一个功能模块通常依赖于某些第三方库,只有当用户引入了这些库,相关的功能 Bean 才应该被创建。

场景:只有当用户在 pom.xml 中引入了 mysql-connector-java 驱动包时,才自动配置一个 MySQL 相关的 Bean。

@Configuration
// 只有当 classpath 中能找到 "com.mysql.cj.jdbc.Driver" 这个类时,
// 这个配置才会生效。
@ConditionalOnClass(name = "com.mysql.cj.jdbc.Driver")
public class MySqlRelatedConfiguration {
    
    @Bean
    public MySqlHealthIndicator mySqlHealthIndicator() {
        // 创建一个检查 MySQL 健康状态的 Bean
        return new MySqlHealthIndicator();
    }
}
4. @ConditionalOnWebApplication 和 @ConditionalOnNotWebApplication

条件:判断当前应用是否是一个 Web 应用(例如,classpath 中有 Spring MVC 或 WebFlux)。

场景:某些 Bean(如 Filter, Interceptor, WebMvcConfigurer)只在 Web 环境下才有意义。

@Configuration
@ConditionalOnWebApplication // 只有是Web应用时才生效
public class WebSpecificConfig {

    @Bean
    public MyCustomFilter myCustomFilter() {
        return new MyCustomFilter();
    }
}

综合示例:智能通知服务

假设我们要构建一个通知服务,默认使用邮件,但如果用户配置了短信,则优先使用短信。

// 1. application.properties (用户可以不配置,或配置为sms)
// notification.channel=sms

// 2. 核心配置类
@Configuration
public class NotificationAutoConfiguration {

    // 方案A:如果用户配置了短信渠道,创建 SmsService
    @Bean
    @ConditionalOnProperty(name = "notification.channel", havingValue = "sms")
    public NotificationService smsNotification() {
        System.out.println("Condition met: Creating SmsNotificationService.");
        return new SmsNotificationService();
    }

    // 方案B:如果容器里还没有任何 NotificationService 的 Bean,
    // 就创建一个默认的 EmailService 作为“兜底”方案。
    @Bean
    @ConditionalOnMissingBean(NotificationService.class)
    public NotificationService emailNotification() {
        System.out.println("No other NotificationService found. Creating default EmailNotificationService.");
        return new EmailNotificationService();
    }
}

运行结果分析:

  • 如果用户配置 notification.channel=sms:SmsNotificationService 会被创建。因为此时容器中已经有了 NotificationService 类型的 Bean,所以 EmailNotificationService 的 @ConditionalOnMissingBean 条件不满足,它不会被创建。最终注入的是 SmsNotificationService。
  • 如果用户没有配置 notification.channel:SmsNotificationService 的 @ConditionalOnProperty 条件不满足,它不会被创建。此时容器中没有任何 NotificationService 类型的 Bean,所以 EmailNotificationService 的 @ConditionalOnMissingBean 条件满足,它会被创建。最终注入的是 EmailNotificationService。

总结

注解条件主要用途
@ConditionalOnProperty配置文件中属性的值功能开关,按配置切换实现
@ConditionalOnMissingBeanIoC 容器中缺少某个 Bean提供可被用户覆盖的默认实现(兜底 Bean)
@ConditionalOnBeanIoC 容器中存在某个 Bean当某个依赖准备好后,才装配当前 Bean
@ConditionalOnClassClasspath 中存在某个类检测是否引入了某个依赖库,是开发 starter 的核心
@ConditionalOnWebApplication当前是 Web 应用环境装配只在 Web 环境下有意义的 Bean
@Conditional自定义 Condition 类实现高度定制化的、复杂的判断逻辑

通过灵活运用这些条件注解,你就可以编写出非常智能、健壮、可插拔的模块,这也是 Spring Boot “约定优于配置”理念的精髓所在。

400G光模块测试全攻略:从PCS层到CMIS合规的避坑指南 本文为网络设备测试工程师和光通信研发人员提供了一份详尽的400G光模块测试实战指南。文章深入剖析了从PCS层信号完整性、FEC容限到CMIS管理接口合规性测试的全流程,并分享了ANLT协议分析、SerDes眼图调试以及系统级流量压力测试中的核心技巧与常见避坑点,旨在帮助读者构建一套高效、精准的测试体系,确保高速光模块的可靠性与性能。 阅读详情

相关推荐

nbiot和2g_浅谈NBIOT

一、什么是NBIOT?1、概念窄带物联网(Narrow Band Internet of Things, NB-IoT),NB-IoT构建于蜂窝网络,只消耗大约180KHz的带宽,使用License频段,可采取带内、保护带或独立载波等三种部署方式,与现有网络共存。可直接部署于GSM网络、UMTS网络或LTE网络,以降低部署成本、实现平滑升级。2、NBIOT的特点和目标(1)超强覆盖:相对GPRS来...

weixin_39534100的博客 1704

Spring高手之路9——掌握Spring条件装配的秘密武器

在Spring框架中,条件装配是一个强大的功能,可以帮助我们更好地管理和控制Bean的创建过程。本文详细解释了如何使用Spring的@Profile和@Conditional注解实现条件装配,通过具体的示例可以更好地理解这两个注解的用法和适用场景。深入研究这些注解,可以帮助提升Spring应用开发的技能,更好地掌握Spring框架。

卓越无关环境,保持空杯心态——靡不有初,鲜克有终 1万+

SAP期初库存导入 (1)

LSMW

IT养家 7189

@Conditional 条件装配注解

@Conditional 条件装配: 满足Conditional指定的条件,则进行组件注入 Conditional还是个根注解,它下面还派生了非常多的注解,注解的功能可以来看一下Conditional 在IDEA中找到@Conditional注解: package org.springframework.context.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; i

yasinawolaopo的博客 1000

解决 PyInstaller 与 `pathlib` 包不兼容的问题

为了避免 PyInstaller 和pathlib包的兼容性问题,最简单的解决办法就是卸载不必要的pathlib包。只需在命令行中运行卸载命令,然后重新打包即可。

Winfredzhang的博客 3225

电信光猫隐藏的VOIP功能揭秘:不用座机也能打电话(EasySip实战)

本文揭秘了电信光猫隐藏的VOIP功能,通过EasySip实战演示如何无需座机实现高清通话。详细解析了光猫的SIP协议支持、语音VLAN配置及网络架构优化,帮助用户利用现有设备提升通话质量并扩展设备兼容性,特别适合智能家居和企业级应用场景。

weixin_29268385的博客 755

《SpringBoot系列十三》:图文精讲@Conditional条件装配实现原理

1、@Conditional条件装配实现原理? 2、什么时候进行条件装配? 3、条件装配的两个阶段介绍一下? 4、@ConditionalOnClass实现原理? 5、@ConditionalOnBean实现原理?

健身变秃,coding变强 4892

怎样自己亲手搭建一个四比特加法器

如何用三极管搭建一个四比特加法器 一、前言 作为大一上学期第一个大作业,最终还是拖到了冬学期的第八周,从第七周的周六开始,一直到第八周周五上午课上展示,中间连续熬了好几天的夜,另外,白天凡是有时间都用在研究它了,最终大约是用了30个小时,完成了这个四比特加法器的“从零到一”。 最终,小组得分92,个人分数100(贡献比35%),也不枉自己投入的心血 二、器材 电阻 1 包(10kΩ×100,1kΩ×50) 三极管 1 包(9013×100,LED×6) 跳线 3 短 1.5 长 电源 1 个 USB 线

qq_34771124的博客 1万+

解密Spring Boot:深入理解条件装配与条件注解

这篇文章将深入探讨Spring Boot中条件装配与条件注解的重要性和应用。它将解密这些概念,帮助读者更好地理解如何根据特定条件来决定是否创建bean或配置应用程序的行为。通过详细介绍条件装配的工作原理和条件注解的使用方法,读者将能够更好地利用Spring Boot框架的强大功能来构建灵活且高度可配置的应用程序。这篇文章将为读者提供清晰的指导,帮助他们更好地利用条件装配和条件注解来优化他们的Spring Boot应用程序。

忆~遂愿的博客 5133

从Reset到Read:深入解析Rolling Shutter曝光流水线

本文深入解析Rolling Shutter(卷帘曝光)的工作原理,重点探讨Reset和Read信号在图像传感器中的关键作用。通过Reset-Read流水线机制,详细解释了曝光控制、时序调优及运动伪影补偿等核心技术,帮助读者理解卷帘曝光在高速摄影和动态场景中的应用。

weixin_42531925的博客 253

SAP_MM模块库存概览俄罗斯报表简介

本文介绍了SAP MM模块中"库存概览俄罗斯报表"的功能与应用。该报表主要用于查看物料在不同库存地点和类型的库存情况,并满足俄罗斯当地法规要求。文章解释了"俄罗斯报表"可能指代本地化合规库存报表或客户自定义报表,详细说明了事务代码J3RFLVMOBVEDH的操作步骤,包括公司代码、物料编码、日期范围等查询条件,并解释了报表中各字段含义如期初期末库存数量与价值。最后强调在物料分类账处理完成后使用该报表可获得实际库存价值,为SAP用户提供了实用的库存管理参考。

我小时候很黑的博客 1086

详解 Spring Boot 条件装配

Spring Boot 条件装配是一种强大的特性,它允许我们根据不同的条件来选择性地启用或禁用特定的配置。在实际开发中,我们应该根据具体的需求和场景,合理地使用条件装配,以实现最佳的设计效果。Spring Boot 条件装配是一种强大的特性,它允许开发者根据不同的条件来选择性地启用或禁用特定的配置。Spring Boot 条件装配基于 Spring Framework 的条件注解(@Conditional),它定义了一组条件,只有当这些条件满足时,相关的配置才会被激活。条件注解可以应用于类、方法或字段上。

csbysj2020 1128

MATLAB与ROS联合仿真——ROS环境搭建及相关准备工作(上)

本篇文章主要介绍在安装完ROS后,在进行MATLAB与ROS联合仿真之前,需要进行的一些环境搭建以及准备工作,主要分为 创建ROS工作空间及功能包、必备功能包安装、安装Gazebo11、导入实验功能包至工作空间、安装Visual_Studio_Code(选做)、常用便捷工具安装(选做) 六部分。    本部分内容共分为上下两篇,上篇包括创建ROS工作空间及功能包和必备功能包安装这两部分,下篇包括、安装Gazebo11、导入实验功能包至工作空间、安装Visual_Studio_Code(选做)、常用便捷工

慕羽★的博客 3361

【Java教程】Day22-09 Spring框架:IoC容器——条件化Bean的创建与装配

​在开发应用程序时,我们常常需要根据不同的环境进行适配。例如,开发环境使用内存数据库以便快速启动,而生产环境使用真正的数据库,如MySQL。如果应用程序能够根据不同的环境配置自动适配,便能够提高灵活性和可维护性。 Spring框架为此提供了@Profile和@Conditional等注解,帮助我们根据不同条件动态加载和装配Bean。本文将介绍如何使用这些功能,使得Spring容器能够根据环境条件灵活地创建和管理Bean。

max202011161630的博客 719

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

Spring bean的装配方式

文档: 关于Spring IOC (DI-依赖注入)你需要知道的一切https://blog.youkuaiyun.com/javazejian/article/details/54561302 bean 什么是bean In Spring, the objects that form the backbone of your application and that are managed by ...

bin1029的博客 254

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

Spring IOC学习(02)Bean的高级装配

内容概览 环境与profile 条件化的bean 自动装配的歧义性 Bean的作用域 运行时值注入 总结 1. 环境与profile 在项目开发的过程中,不可避免的一个问题是项目需要在不同的环境之间运行与切换,比如最经典的例子,通常大部分中小型的项目分为开发(dev),测试(test),生产(prod)三个环境,这三个环境中,配置的数据库,缓存,常量或者秘钥等内容非常有可能是不同的,环境的切换通常非常有可能引发非预期的问题,详细大家都深有体会。 这种多

Blues的专栏 501

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

Spring系列开篇 — 核心功能IoC和AOP 知识点总结

环绕通知,最强大的通知。其方法形参中必须包含一个ProceedingJoinPoint对象,可以通过这个对象上的getArgs方法获取被拦截的目标对象的方法入参,通过proceed方法执行原目标对象的方法。@Bean:注解在方法上,方法的返回值对象会注册到Spring容器(常用于创建第三方jar包中的类对象)。使用@Primary注解(@Primary与@Component搭配,或@Primary与@Bean搭配)(只能有一个首选bean,当出现多个首选bean时,Spring仍然不知道该注入哪一个)

vvoennvv的博客 113

Spring in Action学习笔记(1)

Spring基础 IoC 控制反转, 也称为DI-依赖注入 一、装配bean 推荐顺序:自动装配 -> JavaConfig装配 -> XML装配 1. 自动装配 @Component 注解:表明该类会作为组件类,并告知Spring要为这个类创建bean。该bean的ID为第一个字母小写的类名; @ComponentScan 注解:告诉Config配置类启用组件扫描,默认扫描的基...

weixin_30411997的博客 139

02.spring framework的IOC

待续

mazhongjia的博客 316

Spring框架源码深度解析:从IOC容器到Spring Boot自动装配

依赖注入(DI)和控制反转(IOC)是现代Java企业级应用开发的基石,它们通过将对象创建与依赖管理的控制权从应用程序代码转移到容器,实现了组件间的松耦合。其核心原理在于容器负责管理对象的生命周期和依赖关系,开发者只需声明依赖,容器在运行时动态注入。这一机制的技术价值在于提升了代码的可测试性、可维护性和可扩展性,使得大型应用架构更加清晰。在典型的Web应用场景中,从HTTP请求处理到数据库操作,整个链路都依赖于IOC容器对Bean的管理。本文以Spring框架为例,深入剖析其**IOC容器**如何通过**三

weixin_28481133的博客 286

装配Spring Bean

1、依赖注入的三种方式 构造器注入 setter注入 接口注入 构造器注入和setter注入是最主要的方式 1.1 构造器注入 package com.learn.ssm.pojo; import java.io.Serializable; public class Role implements Serializable { private int id; privat...

weixin_41545613的博客 178

Spring IOC之总结篇

  一、前言   本人最近刚看完《Spring实战 第四版》这本书,也整理写了一些demo。本着复习和分享的心态,题主从今天开始会陆续分享一些Spring的相关教程,欢迎各位来查看评论。 二、Spring IOC概念解析   由于网上对Spring IOC的相关概念已经有了很清晰的讲解了,题主在此就不赘述了。这里推荐一篇文章谈谈对Spring IOC的理解,该篇通俗易懂解释了什么是IO...

qq_37771475的博客 354

详细说说Spring的IOC机制

Spring 的 IOC(控制反转)是框架的核心机制,用于管理对象的创建和依赖注入,通过将控制权从应用程序代码转移到容器,实现组件间的解耦。传统开发中,对象主动创建依赖,导致紧耦合。IOC 将对象创建和依赖管理的控制权交给 Spring 容器,由容器负责实例化、配置和组装对象。IOC 的具体实现方式,容器通过构造器、Setter 方法或字段注入,将依赖对象传递给目标组件。

大户影视的博客 1675

Spring IOC核心原理与运用

实现线程局部作用域的完整示例:@Override@Override@Override// 线程销毁时清理@Override@Bean@Component// 或通过@Scope的proxyMode创建代理@Component// 多租户数据源实现。

EscaRC的博客 1208

Spring系列(1)-装配Spring Bean

本章介绍的内容可查阅如下思维导图: 依赖注入 在实际环境中实现Ioc容器的方式主要分为:依赖查找和依赖注入 二者关系 : 我们知道Spring是先完成Bean的定义和生成,然后在寻找需要注入的资源,找到对应的类型然后将其注入,完成依赖注入. 依赖注入有三种方式:构造器注入,setter注入和接口注入. 构造器注入 构造器注入依赖于构造方法来实现,Spring也可以通过使用构造方法来完成...

wt的博客 329

springBoot的自动装配

5、在解析@Import注解的时候,会有一个getImport()方法,从主类开始递归解析注解,把所有包含@Import的注解都解析到,然后在processImport()方法中对import的类进行分类,例如AutoConfigurationImportSelect归属于ImportSelect的子类,在后续的过程中会调用DeferredImportSelectorHandler类里面的process方法,来完成整个EnableAutoConfiguration的加载。

HongSuShouyu的博客 2709
上一篇: 面试官:Spring 如何控制 Bean 的加载顺序?
下一篇: Spring Boot 项目中多数据源配置使用场景
冰糖心书房
博客等级 码龄15年 6014粉丝 690原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冰糖心书房

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值