Skip to content

01.4 — 条件装配与作用域

定位: Bean 的作用域管理 + 基于条件的环境化装配 面试高频度: ⭐⭐⭐⭐ 考查方式: 6种作用域区别、@Profile 使用、@ConditionalOnXxx 原理

一、这是什么?为什么需要它?

作用域定义了 Bean 在容器中的生命周期范围——是每个容器一个实例,还是每个请求一个实例。

条件装配让 Bean 的注册可以基于环境条件(类路径、配置属性、环境等)动态决定,是 Spring Boot 自动配置的底层基础。

二、原理拆解

2.1 Bean 作用域对比

作用域说明特点
singleton(默认)每个 IoC 容器一个实例单例、线程安全需自行保证
prototype每次获取/注入创建新实例非单例、Spring 不管理完整生命周期
request每个 HTTP 请求一个实例Web 环境,请求结束后销毁
session每个 HTTP Session 一个实例Web 环境,Session 结束后销毁
application每个 ServletContext 一个实例Web 环境,应用级别
websocket每个 WebSocket 一个实例WebSocket 环境

2.2 prototype 注意事项

  • Spring 创建 prototype Bean 后不再管理其后续生命周期(destroy 方法不会执行)
  • prototype Bean 中的 singleton 依赖仍然正确注入

2.3 @Profile

java
@Configuration
@Profile("dev")  // 仅在 dev 环境下生效
public class DevConfig {
    @Bean
    public DataSource dataSource() {
        return new HikariDataSource();
    }
}
// 激活方式:spring.profiles.active=dev 或 application-dev.yml

2.4 @Conditional 与 Spring Boot 条件注解体系

java
// @Conditional 是 Spring 框架的基础 SPI
public class OnWindowsCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        return System.getProperty("os.name").toLowerCase().contains("windows");
    }
}

@Configuration
@Conditional(OnWindowsCondition.class)
public class WindowsSpecificConfig { ... }

Spring Boot 基于 @Conditional 扩展的条件注解:

注解条件
@ConditionalOnClass类路径存在指定类
@ConditionalOnMissingBean容器中不存在指定 Bean
@ConditionalOnProperty配置项存在/等于某值
@ConditionalOnWebApplication当前是 Web 应用
@ConditionalOnExpressionSpEL 表达式为 true
@ConditionalOnSingleCandidate指定 Bean 只有一个候选

三、面试视角

追问答案要点
singleton Bean 线程安全问题?需自行保证(无状态或用 ThreadLocal)
prototype Bean 的 destroy 方法会执行吗?不会,Spring 创建后不再管理
@Profile 和 @Conditional 的关系?@Profile 是 @Conditional 的特例实现
自定义 Starter 中最常用的条件注解?@ConditionalOnClass、@ConditionalOnMissingBean

📚 相关链接

  • **Spring Boot 板块** — 条件注解是 Spring Boot 自动配置的基础
  • ← 返回 **返回 IoC 容器索引**

Knowledge4J — Java 知识库