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.yml2.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 应用 |
| @ConditionalOnExpression | SpEL 表达式为 true |
| @ConditionalOnSingleCandidate | 指定 Bean 只有一个候选 |
三、面试视角
| 追问 | 答案要点 |
|---|---|
| singleton Bean 线程安全问题? | 需自行保证(无状态或用 ThreadLocal) |
| prototype Bean 的 destroy 方法会执行吗? | 不会,Spring 创建后不再管理 |
| @Profile 和 @Conditional 的关系? | @Profile 是 @Conditional 的特例实现 |
| 自定义 Starter 中最常用的条件注解? | @ConditionalOnClass、@ConditionalOnMissingBean |
📚 相关链接
- **Spring Boot 板块** — 条件注解是 Spring Boot 自动配置的基础
- ← 返回 **返回 IoC 容器索引**