Spring Boot 自动配置靠什么实现?一文读懂 @Conditional 条件注解

图片[1]-Spring Boot 自动配置靠什么实现?一文读懂 @Conditional 条件注解-速优课

很多人用Spring Boot的时候都有一个疑问:

为什么有些Bean会自动生效,有些却不会?

为什么加一个依赖,功能就“自动出现”了?

答案只有一个关键词:@Conditional

这篇文章,我们把Spring Boot条件注解的底层原理,一次讲透(建议收藏)


一、什么是 @Conditional?

一句话解释:

@Conditional = 按条件加载Bean

也就是说:

  • 条件满足 → Bean生效
  • 条件不满足 → Bean不加载

一个简单例子

@Bean
@Conditional(OnWindowsCondition.class)
public User user() {
    return new User();
}

只有在Windows系统下,这个Bean才会生效。


本质就是:

把“if判断”写进Spring容器里


二、核心原理:Condition接口

所有条件注解的底层,都是实现这个接口

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

matches 方法

核心逻辑就在这里:

return true;  // 加载Bean
return false; // 不加载

ConditionContext 能干嘛?

它可以拿到:

  • BeanFactory
  • Environment(配置)
  • ClassLoader
  • ResourceLoader

也就是说,你可以判断:

  • 是否存在某个类
  • 是否有某个配置
  • 当前环境是什么

三、Spring Boot常用条件注解(重点)

Spring Boot帮我们封装了一堆“开箱即用”的条件注解:


1️⃣ @ConditionalOnClass

判断类是否存在

@ConditionalOnClass(name = "redis.clients.jedis.Jedis")

场景:

  • 引入Redis依赖 → 自动配置生效
  • 没引入 → 自动失效

2️⃣ @ConditionalOnMissingBean(超常用)

当容器中没有这个Bean时才生效

@ConditionalOnMissingBean(DataSource.class)

用途:

防止用户自定义Bean被覆盖


3️⃣ @ConditionalOnBean

只有存在某个Bean才生效

@ConditionalOnBean(DataSource.class)

4️⃣ @ConditionalOnProperty(企业最常用)

根据配置文件判断

@ConditionalOnProperty(name = "feature.enabled", havingValue = "true")

application.yml:

feature:
  enabled: true

常用于:

  • 功能开关
  • 灰度控制

5️⃣ @ConditionalOnExpression

支持SpEL表达式

@ConditionalOnExpression("'${env}'.equals('prod')")

6️⃣ @ConditionalOnResource

判断资源是否存在

@ConditionalOnResource(resources = "classpath:config.properties")

四、@Conditional在Spring Boot中的作用(重点)

核心一句话:

Spring Boot自动配置 = @Conditional 的大量使用


来看一个经典例子

@Configuration
@ConditionalOnClass(DataSource.class)
public class DataSourceAutoConfiguration {
}

逻辑是:

  • 有 DataSource 类 → 自动配置数据库
  • 没有 → 不配置

再看一个:

@Bean
@ConditionalOnMissingBean
public ObjectMapper objectMapper() {
    return new ObjectMapper();
}

逻辑:

  • 你没定义 → 我帮你创建
  • 你定义了 → 用你的

这就是:

Spring Boot“智能”的核心原因


五、源码执行流程(面试重点)

在 Spring 容器启动时:

会执行:

ConditionEvaluator.shouldSkip()

核心逻辑:

1️⃣ 扫描所有带 @Conditional 的类或方法

2️⃣ 调用 Condition.matches()

3️⃣ 返回 false → 跳过Bean加载


所以你可以这样理解:

@Conditional = Bean加载的“开关控制器”


六、自定义一个条件注解(实战)

我们自己实现一个


第一步:实现 Condition

public class OnLinuxCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        String os = context.getEnvironment().getProperty("os.name");
        return os != null && os.contains("Linux");
    }
}

第二步:使用

@Bean
@Conditional(OnLinuxCondition.class)
public User user() {
    return new User();
}

只有Linux环境才加载。


七、常见面试问题


Q1:Spring Boot自动配置原理?

答:

  • 基于 @EnableAutoConfiguration
  • 通过 spring.factories 加载配置类
  • 使用 @Conditional 控制是否生效

Q2:@Conditional 和 @Profile 区别?

@Profile:

  • 只针对环境(dev/test/prod)

@Conditional:

  • 更灵活,可以判断任意条件

Q3:为什么需要 @ConditionalOnMissingBean?

防止:

自动配置覆盖用户自定义配置


八、实战总结(重点记住)

Spring Boot核心三板斧:

1.自动配置(AutoConfiguration)

2.条件装配(@Conditional)

3.SPI机制(spring.factories)


而 @Conditional 就是:

让Spring Boot“聪明”的关键机制


九、写在最后

很多人只会用Spring Boot,但真正拉开差距的是:

是否理解底层原理

当你理解了 @Conditional,你就能:

  • 自定义自动配置
  • 做框架扩展
  • 写更优雅的系统

技术的本质不是会用,而是能解释“为什么”。

© 版权声明
THE END
喜欢就支持一下吧
点赞6
相关推荐
评论 抢沙发

请登录后发表评论

    请登录后查看评论内容

温馨提示:
1、本内容转载于网络,版权归原作者所有!
2、本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
3、本内容若侵犯到你的版权利益,请联系我们,会尽快给予删除处理!