spring中的@Conditional注解详解

@Conditional是Spring框架中用于条件化Bean注册的核心注解,它允许开发者根据特定条件动态决定是否将Bean注册到Spring容器中。这一特性在模块化开发、多环境适配和动态配置等场景中非常有用。

在这里插入图片描述


核心原理

@Conditional注解通过实现Condition接口的类来定义条件逻辑。当Spring容器加载配置时,会实例化并调用指定的Condition实现类的matches方法,根据返回值决定是否加载被注解的Bean或配置。

Condition接口

public interface Condition {boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}
  • ConditionContext:提供访问Bean注册表、环境变量、资源加载器等上下文信息的能力。
  • AnnotatedTypeMetadata:允许检查带有注解的类或方法上的其他注解。

基本用法

1. 自定义条件类

首先,需要实现Condition接口并定义条件逻辑:

public class MyCondition implements Condition {@Overridepublic boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {// 示例:检查操作系统是否为WindowsString osName = context.getEnvironment().getProperty("os.name");return osName != null && osName.contains("Windows");}
}

2. 在配置类或方法上使用@Conditional

@Configuration
public class AppConfig {@Bean@Conditional(MyCondition.class)public MyService myService() {return new MyService();}
}
  • MyCondition.matches()返回true时,myService Bean会被注册到Spring容器中;否则,该Bean将被忽略。

常见应用场景

1. 多环境适配

根据不同的运行环境(如开发、测试、生产)加载不同的Bean:

public class DevEnvironmentCondition implements Condition {@Overridepublic boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {return context.getEnvironment().acceptsProfiles("dev");}
}@Configuration
public class DataSourceConfig {@Bean@Conditional(DevEnvironmentCondition.class)public DataSource devDataSource() {return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2).build();}
}

2. 类路径检查

仅当特定类存在于类路径中时才加载Bean:

public class OnClassCondition implements Condition {@Overridepublic boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {try {context.getClassLoader().loadClass("com.example.SomeLibrary");return true;} catch (ClassNotFoundException e) {return false;}}
}@Configuration
public class SomeLibraryConfig {@Bean@Conditional(OnClassCondition.class)public SomeLibraryService someLibraryService() {return new SomeLibraryService();}
}

3. 配置属性检查

根据配置文件中的属性值决定是否加载Bean:

public class OnPropertyCondition implements Condition {@Overridepublic boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {return Boolean.parseBoolean(context.getEnvironment().getProperty("feature.enabled", "false"));}
}@Configuration
public class FeatureConfig {@Bean@Conditional(OnPropertyCondition.class)public FeatureService featureService() {return new FeatureService();}
}

Spring Boot中的扩展

Spring Boot在spring-boot-autoconfigure模块中提供了一系列基于@Conditional的派生注解,简化了常见的条件判断:

  • @ConditionalOnClass:当指定类存在于类路径中时生效。
  • @ConditionalOnMissingClass:当指定类不存在于类路径中时生效。
  • @ConditionalOnBean:当指定的Bean存在时生效。
  • @ConditionalOnMissingBean:当指定的Bean不存在时生效。
  • @ConditionalOnProperty:当指定的属性满足条件时生效。
  • @ConditionalOnResource:当指定的资源存在时生效。
  • @ConditionalOnWebApplication:仅在Web应用环境中生效。
  • @ConditionalOnNotWebApplication:仅在非Web应用环境中生效。

示例:@ConditionalOnProperty

@Configuration
public class MyAutoConfiguration {@Bean@ConditionalOnProperty(name = "app.feature.enabled", havingValue = "true")public MyService myService() {return new MyService();}
}
  • 仅当application.propertiesapplication.yml中配置了app.feature.enabled=true时,myService Bean才会被注册。

高级用法

1. 组合条件

通过@Conditional注解的组合实现多个条件的逻辑“与”:

@Configuration
@Conditional({ConditionA.class, ConditionB.class})
public class CombinedConfig {@Beanpublic MyBean myBean() {return new MyBean();}
}
  • 只有当ConditionAConditionBmatches方法都返回true时,myBean才会被注册。

2. 自定义条件注解

封装常用条件逻辑为专用注解,提高代码可读性:

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Conditional(OnKubernetesCondition.class)
public @interface ConditionalOnKubernetes {
}@Configuration
@ConditionalOnKubernetes
public class KubernetesServiceConfig {@Beanpublic KubernetesService kubernetesService() {return new KubernetesService();}
}

3. 使用SpEL表达式

结合@ConditionalOnExpression实现更灵活的条件判断:

@Configuration
@ConditionalOnExpression("${app.feature.enabled:false} && ${app.mode eq 'advanced'}")
public class AdvancedFeatureConfig {@Beanpublic AdvancedFeature advancedFeature() {return new AdvancedFeature();}
}

注意事项

  1. 条件判断时机:条件判断发生在Bean定义阶段,早于Bean实例化。
  2. 优先级问题@Conditional的优先级高于@Profile
  3. 避免循环依赖:条件判断中不要直接获取Bean实例,以免引发循环依赖。
  4. 调试技巧:通过--debug参数启动Spring Boot应用,查看条件评估报告。

Condition接口原理与介绍

Condition接口是Spring框架中实现条件化配置的核心接口,其设计目的是通过动态判断条件来决定Bean的注册与初始化。该接口与@Conditional注解配合使用,为多环境配置、按需加载组件等场景提供了强大的灵活性。


1. Condition接口的核心原理

Condition接口定义了一个matches方法,该方法返回一个布尔值,用于指示是否满足条件。其签名如下:

public interface Condition {boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}
  • ConditionContext:提供访问Bean注册表、环境变量、资源加载器等上下文信息的能力。
  • AnnotatedTypeMetadata:允许检查带有注解的类或方法上的其他注解。

当Spring容器在启动时解析@Conditional注解时,会实例化并调用指定的Condition实现类的matches方法,根据返回值决定是否加载被注解的Bean或配置。


2. Condition接口的核心作用

  • 动态条件判断:通过matches方法实现自定义逻辑,判断是否满足条件。
  • 灵活配置:允许根据环境变量、类路径、配置属性等动态决定Bean的注册。
  • 模块化支持:在插件化或模块化开发中,可以根据条件加载或跳过特定模块的Bean。

3. Condition接口的实现示例

以下是一个基于环境变量判断的Condition实现示例:

public class ProductionEnvironmentCondition implements Condition {@Overridepublic boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {// 获取环境变量"MY_ENV"的值,默认为"development"String env = context.getEnvironment().getProperty("MY_ENV", "development");// 判断是否为生产环境return "production".equalsIgnoreCase(env);}
}

在配置类中使用该条件:

@Configuration
@Conditional(ProductionEnvironmentCondition.class)
public class ProductionConfig {@Beanpublic SomeService someService() {return new ProductionSomeService();}
}
  • 只有当环境变量MY_ENV的值为production时,ProductionSomeService Bean才会被注册。

4. Condition接口的典型应用场景

  • 多环境适配:根据不同的运行环境(如开发、测试、生产)加载不同的Bean。
  • 类路径检查:仅当特定类存在于类路径中时才加载Bean。
  • 配置属性检查:根据配置文件中的属性值决定是否加载Bean。
  • 操作系统适配:根据不同的操作系统类型加载不同的Bean。

5. Condition接口与Spring Boot的集成

Spring Boot在spring-boot-autoconfigure模块中提供了一系列基于@Conditional的派生注解,简化了常见的条件判断:

  • @ConditionalOnClass:当指定类存在于类路径中时生效。
  • @ConditionalOnMissingClass:当指定类不存在于类路径中时生效。
  • @ConditionalOnProperty:当指定的属性满足条件时生效。
  • @ConditionalOnBean:当指定的Bean存在时生效。
  • @ConditionalOnMissingBean:当指定的Bean不存在时生效。

例如,使用@ConditionalOnProperty根据配置属性决定是否加载Bean:

@Configuration
@ConditionalOnProperty(name = "feature.enabled", havingValue = "true")
public class FeatureConfig {@Beanpublic FeatureService featureService() {return new FeatureService();}
}
  • 只有当application.propertiesapplication.yml中配置了feature.enabled=true时,featureService Bean才会被注册。

6. Condition接口的设计思想

  • 开闭原则:通过扩展Condition接口实现新的条件逻辑,而不修改现有代码。
  • 策略模式:将条件判断逻辑封装为独立的策略类,便于维护和复用。
  • 组合优于继承:通过组合多个Condition实现类,实现复杂的条件逻辑。

7. Condition接口的最佳实践

  • 单一职责:每个Condition实现类应专注于一个特定的条件判断逻辑。
  • 可测试性Condition实现类应易于测试,避免依赖复杂的上下文信息。
  • 文档化:为自定义条件类添加清晰的注释,说明其用途和适用场景。
  • 复用性:将常用的条件逻辑封装为自定义注解,提高代码可读性。

8. Condition接口的注意事项

  • 条件判断时机:条件判断发生在Bean定义阶段,早于Bean实例化。
  • 避免循环依赖:在matches方法中不要直接获取Bean实例,以免引发循环依赖。
  • 优先级问题@Conditional的优先级高于@Profile
  • 调试技巧:通过--debug参数启动Spring Boot应用,查看条件评估报告。

Condition接口总结

Condition接口是Spring框架中实现条件化配置的核心机制,其设计体现了“开闭原则”与“策略模式”的思想。通过灵活组合内置条件与自定义逻辑,开发者可以轻松实现按需加载、多环境适配等复杂场景。掌握其原理与最佳实践,将极大提升Spring应用的模块化与可维护性。

总结

@Conditional注解为Spring应用提供了灵活的条件化装配能力,通过自定义条件逻辑或使用Spring Boot提供的派生注解,开发者可以轻松实现模块化、多环境适配和动态配置等复杂场景。掌握@Conditional的原理与最佳实践,将极大提升Spring应用的模块化与可维护性。


spring中的BeanDefinition接口详解

spring1.x详解介绍

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/79531.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MYSQL-设计表

一.范式 数据库的范式是⼀组规则。在设计关系数据库时,遵从不同的规范要求,设计出合理的关系型数 据库,这些不同的规范要求被称为不同的范式。 关系数据库有六种范式:第⼀范式(1NF)、第⼆范式(…

第三方测试机构在软件测试领域有何重大作用与优势?

第三方测试机构在软件测试领域作用重大,它就像公正的裁判,能帮助确保软件质量,能保障软件可靠性,通过提供专业测试服务,为软件安全性提供保障,也为软件稳定性提供保障。 机构优势 第三方测试机构具有独立…

大模型——使用 StarRocks 作为向量数据库

大模型——使用 StarRocks 作为向量数据库 本章节介绍了 StarRocks,这是一款高性能的分析数据库,并演示了如何将其用作向量数据库。内容涵盖了设置、文档加载、标记化、创建向量数据库实例以及构建一个能够检索的问答系统。 StarRocks StarRocks 是一个次世代的亚秒级 MPP…

怎样增加AI对话的拟人化和增加同理心

怎样增加AI对话的拟人化和增加同理心 随着心理健康问题在大学生中日益普遍,AI聊天机器人被用于提供支持,但如何有效表达同理心成为挑战。本文对比了人与人、人与AI互动中同理心的表达与接收,通过让126名本科生讲述生活事件并收集亚马逊MTurkers的评价,同时使用GPT-4o评估相…

SALOME源码分析:SHAPER模块

本文分析SALOME中的SHAPER模块。 注1:限于研究水平,分析难免不当,欢迎批评指正。注2:文章内容会不定期更新。 一、核心组件 二、关键流程 三、FAQs 网络资料 Introduction to SHAPER

batch normalization和layer normalization区别

Normalization无非就是这样一个操作: 其中x是输入数据,维度为(B,T,C),其中B是batchsize,T是序列长度,C是embedding维度;括号内是标准化操作,γ和…

Postgresql源码(144)LockRelease常规锁释放流程分析

相关 《Postgresql源码(69)常规锁细节分析》 最新遇到一个共享内存损坏导致常规锁释放报错warning "you don’t own a lock of type"的问题。 本篇对常规锁的概念做一些回顾,顺便分析下释放锁的流程。 SpinLock:❎LWL…

基于bert的情感分析程序

文章目录 任务介绍数据概览注意事项数据处理代码准备模型构建与训练模型类构建数据集构建数据批处理模型参数查看模型训练结果推理与评估模型推理准确率评估附录任务介绍 在当今信息爆炸的时代,互联网上充斥着海量的文本数据,如社交媒体评论、产品评价、新闻报道等。这些文本…

宇树科技举办“人型机器人格斗大赛”

2025 年 5 月至 6 月,一场全球瞩目的科技盛宴 —— 全球首场 “人形机器人格斗大赛”,将由杭州宇树科技盛大举办。届时,观众将迎来机器人格斗领域前所未有的视觉震撼。 为打造最强参赛阵容,宇树科技技术团队在过去数周里&#xf…

计算机视觉与深度学习 | 什么是图像金字塔?

图像金字塔详解 图像金字塔 图像金字塔详解1. **定义**2. **原理与公式****2.1 高斯金字塔****2.2 拉普拉斯金字塔**3. **代码示例****3.1 使用OpenCV实现****3.2 手动实现高斯模糊与降采样**4. **应用场景**5. **关键点总结**1. 定义 图像金字塔是一种多尺度图像表示方法,将…

Spring MVC注解式控制器开发

主要对Spring MVC的核心注解的应用进行了详细讲解,介绍了Controller和RequestMapping注解类型的相关知识。 1.注解式控制器概念 Spring2.5之前,我们都是通过实现框架提供的Controller接口来定义我们的处理器类。 Spring2.5引入注解式处理器支持&#…

thonny提示自动补全功能

THONNY IDE 自动补全功能配置 在 Thonny IDE 中启用和优化自动补全功能可以显著提升编程体验。为了确保该功能正常工作,需要确认几个设置选项。 配置自动补全 Thonyy IDE 的自动补全默认情况下是开启的。如果发现自动补全未按预期运行,可以通过调整首选…

D. 例题3.2.2 整数划分问题

题目描述 将正整数n表示成一系列正整数之和:nn_1n_2...n_knn1​n2​...nk​,其中8\geq n_1\geq n_2\geq ...\geq n_k\geq 18≥n1​≥n2​≥...≥nk​≥1,k\geq1k≥1。正整数n的这种表示称为正整数n的划分。 例如正整数6有如下11种不同的划分…

电脑RGB888P转换为JPEG方案 ,K230的RGB888P转换为JPEG方案

K230开发板本身具备将RGB888P转换为JPEG的能力,但需要正确调用硬件或软件接口。以下是具体分析及解决方案: 一、K230原生支持性分析 1. 硬件支持 K230的NPU(神经网络处理器)和图像处理单元(ISP)理论上支持…

图解 Git 工作流:理解 Rebase、Merge 与 Pull Request 的区别

图解 Git 工作流:理解 Rebase、Merge 与 Pull Request 的区别 在多人协作开发中,选择合适的 Git 分支管理策略至关重要。Merge、Rebase 和 Pull Request 是最常见的三种方式,它们本质不同,使用场景也不同。 本文将通过流程图&am…

Dart和Go语言特征对比

文章目录 Dart 和 Go 语法对照表字符串常用方法对照列表(数组/切片)常用方法对照Map (字典/哈希表) 使用对照IO 操作对照文件操作标准输入输出网络IO 主要差异说明 有同事说,我前端用Flutter,后端用Golang,都师出名门。但两个语言还是老打架&…

ActiveMQ 集群搭建与高可用方案设计(二)

五、高可用方案设计与优化 (一)Zookeeper 在 ActiveMQ 集群中的应用 作用:在 ActiveMQ 集群中,Zookeeper 扮演着至关重要的角色。它主要用于选举 Master 节点,通过其内部的选举机制,从众多的 ActiveMQ Br…

【项目归档】数据抓取+GenAI+数据分析

年后这两个月频繁组织架构变动,所以博客很久没更新。现在暂时算是尘埃落定,趁这段时间整理一下。 入职九个月,自己参与的项目有4个,负责前后端开发,测试,devops(全栈/doge)&#xff…

服务器热备份,服务器热备份的方法有哪些?

服务器热备份是保障业务连续性的重要技术手段,通过实时数据同步和快速故障切换,确保在主服务器故障时备份服务器能无缝接管。以下是常见的服务器热备份方法及其核心要点: 双机热备(Active-Standby/Active-Active) 主备…

【AI平台】n8n入门6:调用MCP服务(非社区节点)

前言 前边用n8n搭建一个MCP服务,现在,用n8n调用其他服务商提供的MCP服务。本文以高德地图服务为例,记录一下操作过程。 实现案例功能 MCP是啥 MCP(Model Context Protocol,模型上下文协议)是由Anthropi…