Bean 的生命周期,指的是一个对象在 Spring 容器中,从创建、初始化,到被使用,再到最终销毁所经历的完整过程。
这道题是面试高频题,但很多人备考时习惯去网上找帖子背图。
其实不需要死记硬背,把核心阶段理解透,自然能用自己的话讲清楚。
BeanFactory 接口的源码注释中明确说明,它的实现类应当支持标准的 Bean 生命周期接口,并给出了标准初始化方法及其顺序。
一、源码入口:从 refresh 到 doCreateBean
在refresh()流程中,Bean 的创建最终会进入finishBeanFactoryInitialization()。
这里会遍历容器中所有需要初始化的 Bean(Bean 名先被收集进beanNames集合),并依次调用getBean()完成实例化。
getBean()内部继续进入doGetBean()。
当缓存中不存在目标 Bean 时,会进一步调用createBean(),最终来到真正负责创建对象的doCreateBean()。
Spring 源码中很多以 do 开头的方法承担核心执行逻辑,分析源码时通常需要重点关注。
二、实例化:靠反射生成对象
createBeanInstance()的职责就是完成 Bean 实例化。
Spring 底层仍然采用 Java 反射创建对象,本质流程与手写反射一致:
先获取Class对象,再获取构造器,最后通过反射调用构造方法生成实例。
实际代码中多数是无参构造,因此会通过getDeclaredConstructor()获取无参构造器,再交由BeanUtils工具类调用ctor.newInstance()完成实例化。
三、填充属性:populateBean
实例化完成后进入populateBean(),负责为 Bean 注入依赖和属性值。
属性注入完成后,Bean 还不能立即对外提供服务。
接下来进入初始化阶段,这也是 Bean 生命周期最重要的一部分。
四、初始化:Aware、后置处理器与初始化方法
初始化阶段首先处理各种 Aware 接口,例如BeanNameAware、BeanFactoryAware等。
Spring 会把容器相关信息注入 Bean,使其能够感知自身所处的运行环境。
随后执行BeanPostProcessor的前置方法postProcessBeforeInitialization()。
之后进入初始化方法:
- 如果 Bean 实现了
InitializingBean接口,会调用afterPropertiesSet()。Bean 的创建全程由容器完成,若需要在属性装配完成后执行收尾逻辑,afterPropertiesSet()是常用的扩展点。 - 如果配置中指定了
init-method,会执行对应的自定义初始化方法,不过这种方式相对少用。
最后执行BeanPostProcessor的后置方法postProcessAfterInitialization()。
如果 Bean 需要增强,例如使用 AOP,这一步会返回代理对象,而不是最初创建的原始对象。
| 初始化方式 | 使用方式 | 推荐程度 |
|---|---|---|
| InitializingBean | 实现接口,重写afterPropertiesSet() | 常用扩展点,属性装配后的收尾机会 |
| init-method | 配置中指定自定义方法名 | 相对少用 |
后置方法执行完毕,Bean 的创建流程就全部完成。
五、使用与销毁
初始化完成后,Bean 即可对外提供服务,通过getBean()获取使用。
容器关闭时,Bean 进入销毁阶段,销毁方式与初始化对应:
- 如果 Bean 实现了
DisposableBean接口,会调用destroy()方法,释放资源一类的收尾逻辑通常放在这里。 - 如果配置中指定了
destroy-method,会执行对应的自定义销毁方法,同样相对少用。
需要注意的是,容器只负责单例 Bean 的销毁,prototype 作用域的 Bean 交出实例后便不再归容器管理。
整个 Bean 生命周期可以归纳为下面八个阶段:
实例化(反射生成对象)→ 填充属性 → 调用 Aware 接口 → 执行 BeanPostProcessor 前置 → 初始化(afterPropertiesSet / init-method)→ 执行 BeanPostProcessor 后置(AOP 代理通常在此阶段生成)→ 使用 → 销毁。