先解释一下什么叫spring的bean
其实就是类注册到spring容器里
在这一层,我们应该掌握哪些信息,才算完整成熟
1.bean的生命周期有哪几种类型,也就是类的作用域,这句话不能见名知意,其实还是说,bean的生命周期的类型好一点
2.bean的线程安全问题
3.bean的多环境配置问题
4.Bean的装配方式
5.bean如何在初始化的阶段,如何做特定操作@PostConstruct
6.bean如何读取yaml上的文件
7.条件化配置@contional
明白了,你重新整理了这 7 个知识点,并且希望我先解释"什么是 Spring Bean",然后对每一点给出"成熟掌握"的标准。下面我会按照你的列表逐一说明。
一、什么是 Spring Bean?
Spring Bean 是由 Spring IoC 容器管理的对象 。
简单说:你写一个普通 Java 类(比如 UserService),通过 XML、注解或 Java 配置告诉 Spring:"这个类由你创建、管理、组装、销毁"。
Spring 就会创建它的实例,放到容器里,需要时直接注入使用。
所以"类注册到 Spring 容器里"这个理解基本正确,更完整的定义是:Bean 是 Spring 容器中被实例化、组装和管理的对象。
二、对每个知识点,成熟开发者应掌握到什么程度?
1. Bean 的生命周期有哪几种类型(也就是类的作用域)
这里你把"生命周期类型"说成了"作用域",两者不同,但可以一起掌握:
- 作用域(Scope) -- Bean 实例存在的范围
singleton(默认):整个容器只有一个实例prototype:每次获取都创建新实例request/session/application:用于 Web 环境
- 生命周期 -- Bean 从创建到销毁的过程
- 实例化 → 属性赋值 → 初始化回调(
@PostConstruct)→ 使用 → 销毁回调(@PreDestroy)
- 实例化 → 属性赋值 → 初始化回调(
成熟标准:
- 能说出 4~5 种作用域,知道
singleton和prototype的核心区别(实例数量、生命周期管理程度) - 能画出 Bean 生命周期的关键阶段,并知道在哪里插入自定义逻辑
2. Bean 的线程安全问题
- 问题根源 :默认
singletonBean 只有一个实例,如果它包含了可变状态(实例变量),多线程访问时可能发生数据错乱。 - 解决方案 :
- 设计为无状态(推荐,如 Service 层只做方法调用,不存数据)
- 使用
ThreadLocal存储线程独有数据 - 改为
prototype作用域 - 加同步锁(性能差,不推荐)
成熟标准:
- 能快速判断一个 Bean 是否线程安全
- 知道如何在
Controller/Service/Repository中处理线程安全 - 理解"无状态"是默认最佳实践
3. Bean 的多环境配置问题
指:开发、测试、生产环境使用不同的 Bean 配置(比如不同数据库、不同 MQ)。
实现方式:
@Profile注解:@Profile("dev")/@Profile("prod")- Spring Boot 的
application-{profile}.yml - 通过环境变量或启动参数指定
spring.profiles.active
成熟标准:
- 能熟练使用
@Profile区分环境 - 知道如何激活 profile(命令行、测试注解、配置文件)
- 了解
@ConditionalOnProperty比@Profile更灵活(见第7点)
4. Bean 的装配方式
指:将 Bean 交给 Spring 管理的几种写法。
| 方式 | 示例 | 适用场景 |
|---|---|---|
| XML 配置 | <bean id="user" class="..."/> |
老旧项目 |
| 注解 + 组件扫描 | @Component / @Service + @ComponentScan |
自己写的类 |
| Java Config | @Configuration + @Bean 方法 |
第三方类、复杂初始化 |
@Import |
@Import(OtherConfig.class) |
组合配置类 |
| FactoryBean | 实现 FactoryBean 接口 |
复杂创建逻辑 |
成熟标准:
- 日常开发首选注解 + 组件扫描或 Java Config
- 知道
@Bean方法和@Component的区别(前者用于第三方类,后者用于自己可控的类) - 了解
@Import和@ComponentScan的不同作用范围
5. Bean 在初始化阶段如何做特定操作(如 @PostConstruct)
常用三种方式:
-
@PostConstruct(推荐)java@PostConstruct public void init() { ... } -
@Bean(initMethod = "init")java@Bean(initMethod = "init") public MyBean myBean() { ... } -
实现
InitializingBean接口(不推荐,Spring 耦合)
成熟标准:
- 能说出三种初始化回调及执行顺序:
构造器 → 依赖注入 →@PostConstruct→afterPropertiesSet()→ initMethod - 能区分
@PostConstruct和@PreDestroy - 知道
BeanPostProcessor可以对所有 Bean 做统一初始化后置处理
6. Bean 如何读取 YAML 上的文件
Spring Boot 中读取 YAML 配置的两种主流方式:
| 方式 | 示例 | 特点 |
|---|---|---|
@ConfigurationProperties |
@ConfigurationProperties(prefix="app") |
类型安全,绑定到类字段 |
@Value |
@Value("${app.name}") |
单值注入,支持 SpEL |
成熟标准:
- 知道 YAML 文件通常放在
resources/application.yml - 能编写
@ConfigurationProperties类并启用(@EnableConfigurationProperties或@Component) - 理解
@ConfigurationProperties支持宽松绑定(如app-name→appName) - 知道
@PropertySource默认不支持 YAML,但在 Spring Boot 中可以配合@PropertySource+YamlPropertySourceFactory
7. 条件化配置 @Conditional
@Conditional 及其派生注解用于满足条件时才创建某个 Bean。
常用派生注解(Spring Boot):
@ConditionalOnClass/@ConditionalOnMissingClass@ConditionalOnBean/@ConditionalOnMissingBean@ConditionalOnProperty@ConditionalOnExpression
自定义 :实现 Condition 接口,重写 matches() 方法。
成熟标准:
- 能举例用
@ConditionalOnProperty根据配置开关决定是否创建 Bean - 知道
@ConditionalOnMissingBean是实现自动配置可覆盖的关键 - 能编写一个简单的自定义 Condition(例如判断是否 Windows 操作系统)