当前位置: 首页 > article >正文

Spring中@Conditional注解详解:条件装配的终极指南

一、为什么要用条件装配?

在实际开发中,我们经常需要根据不同的运行环境配置参数依赖情况动态决定是否注册某个Bean。例如:

  • 开发环境使用内存数据库,生产环境连接真实数据库

  • 当存在某个类时才启用特定功能

  • 根据配置文件开关决定是否初始化组件

这时就需要用到Spring的条件装配机制,而@Conditional注解正是实现这一功能的核心!

二、@Conditional注解简介

1. 核心作用

@Conditional是Spring 4.0引入的条件化Bean注册注解,通过它可以实现:

if(满足指定条件) {
    注册当前Bean
}

2. 核心接口

其底层依赖Condition接口:

public interface Condition {
    boolean matches(ConditionContext context, 
                   AnnotatedTypeMetadata metadata);
}

3. 常见派生注解

Spring Boot基于它扩展了:

  • @ConditionalOnProperty

  • @ConditionalOnClass

  • @ConditionalOnMissingBean

  • 等20+条件注解

三、使用方式(三步走)

步骤1:自定义条件类

public class MyCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, 
                          AnnotatedTypeMetadata metadata) {
        // 返回true则创建Bean
        return checkSomeCondition(); 
    }
}

步骤2:标注条件注解

@Configuration
public class AppConfig {
    
    @Bean
    @Conditional(MyCondition.class) // 关键注解
    public MyService myService() {
        return new MyService();
    }
}

步骤3:验证结果

MyCondition.matches()返回true时,MyService会被注册到容器,否则忽略。

四、实战案例:多环境配置

场景描述

根据不同的运行环境(dev/test/prod)加载不同的数据源配置。

1. 定义环境条件
public class EnvCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, 
                          AnnotatedTypeMetadata metadata) {
        // 获取环境变量
        String env = context.getEnvironment()
                          .getProperty("app.env", "dev");
        // 获取注解中定义的目标环境
        Map<String, Object> attrs = metadata.getAnnotationAttributes(
            ConditionalOnEnv.class.getName());
        String targetEnv = (String) attrs.get("value");
        
        return targetEnv.equalsIgnoreCase(env);
    }
}

// 自定义条件注解
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Conditional(EnvCondition.class)
public @interface ConditionalOnEnv {
    String value();
}
2. 配置不同环境Bean
@Configuration
public class DataSourceConfig {

    // 开发环境数据源
    @Bean
    @ConditionalOnEnv("dev")
    public DataSource devDataSource() {
        return new EmbeddedDatabaseBuilder()
            .setType(EmbeddedDatabaseType.H2)
            .build();
    }

    // 生产环境数据源
    @Bean
    @ConditionalOnEnv("prod")
    public DataSource prodDataSource() {
        HikariDataSource ds = new HikariDataSource();
        ds.setJdbcUrl("jdbc:mysql://prod-server:3306/db");
        // 其他配置...
        return ds;
    }
}
3. 测试验证
// 设置环境变量
System.setProperty("app.env", "prod");

ApplicationContext ctx = new AnnotationConfigApplicationContext(
    AppConfig.class);
// 生产数据源将被注入
DataSource dataSource = ctx.getBean(DataSource.class); 

五、高级用法:组合条件

多个条件可以通过AllNestedConditions实现逻辑与

public class AllConditions extends AllNestedConditions {
    
    public AllConditions() {
        super(ConfigurationPhase.REGISTER_BEAN);
    }

    @ConditionalOnClass(DataSource.class)
    static class OnClassCondition {}

    @ConditionalOnProperty("spring.datasource.url")
    static class OnPropertyCondition {}
}

// 使用组合条件
@Configuration
@Conditional(AllConditions.class)
public class DataSourceAutoConfiguration {
    // 当类路径存在DataSource且配置了url时生效
}

六、注意事项

  1. 条件判断时机:发生在Bean定义阶段,早于Bean实例化

  2. 优先级问题@Conditional的优先级高于@Profile

  3. 避免循环依赖:条件判断中不要直接获取Bean实例

  4. 调试技巧:通过-Ddebug查看条件评估报告(Spring Boot)

七、总结

@Conditional为Spring应用提供了灵活的条件装配能力,通过本文你可以:

✅ 掌握自定义条件装配的实现方法
✅ 了解多环境配置的最佳实践
✅ 学会处理复杂条件组合场景


http://www.kler.cn/a/531333.html

相关文章:

  • Jupyterlab和notebook修改文件的默认存放路径的方法
  • DeepSeek超越ChatGPT的能力及部分核心原理
  • 三路排序算法
  • 【Pytorch和Keras】使用transformer库进行图像分类
  • 首发!ZStack 智塔支持 DeepSeek V3/R1/ Janus Pro,多种国产 CPU/GPU 可私有化部署
  • 【Proteus】NE555纯硬件实现LED呼吸灯效果,附源文件,效果展示
  • 8、面向对象:类、封装、构造方法
  • pandas中的关系型连接操作
  • 1.5 Go切片使用
  • 浅谈量化感知训练(QAT)
  • 机器学习--学习计划
  • Intel 与 Yocto 项目的深度融合:全面解析与平台对比
  • 变形金刚多元宇宙
  • 【汽车电子软件架构】AutoSAR从放弃到入门专栏导读
  • 【探索篇】探索部署离线AI在Android的实际体验
  • ChatGPT提问技巧:行业热门应用提示词案例--办公应用
  • SpringAI 人工智能
  • Pandas基础08(分箱操作/时间序列/画图)
  • [SAP ABAP] 性能优化
  • 解决注入线程池的栈溢出问题
  • [LeetCode] 字符串完整版 — 双指针法 | KMP
  • 【Python】容器
  • 双目标定与生成深度图
  • AP单类平均准确率
  • MySQL 插入数据指南
  • 一文读懂 RAG:LLM 借助检索打开思路