Bean 是 Spring 对组件的抽象,Bean 的创建、销毁都由 Spring 控制。使用过程中我们会希望定制创建、销毁过程中的部分逻辑,于是作为框架的 Spring 需要提供相应的机制。我们关心 Bean 的生命周期,就在于需要了解可以定制的部分。

Bean 创建过程

Bean 的创建过程如下,这些阶段 Spring 都提供了定制的手段:

上图中需要注意下面几点:

  • ① 中已经完成依赖注入。
  • ②、③、④ 为代表的这些 Aware 接口,一般用于向 Bean 中注入 Spring 的组件。个人常用的是 ④,注入 ApplicationContext 后续用来获取 Prototype Scope 的 Bean 。除了图中画的,还有其它的 Aware 接口
  • ⑥、⑦、⑧ 可以为 Bean 指定初始化方法,当前建议只用 @PostConstruct。如果同时使用不同手段指定同一个方法作为 Bean 的初始化方法,则该方法只会被调用一次。
  • 与其它阶段不同,⑤ 与 ⑨ 是 BeanFactory 级别的定制,其它阶段则是 Bean 级别的。

上面列出的是单个 Bean 创建时各个阶段的顺序,那不同 Bean 创建的相对顺序呢?

一个 Bean 在 Populate Properties 时就完成了依赖注入,如果 Bean X 依赖 Bean Y,那么在 X 的依赖注入时 Y 就需要处于 Ready 状态。换句话说被依赖的 Bean Y 走完了所有流程后Bean X 才开始创建。但如果两个 Bean 间没有依赖关系,则没有这个保证。

Bean 的销毁过程

Bean 的销毁过程如下,推荐使用 @PreDestroy 的方式。另外注意:对于 Prototype Scope 的 Bean,Spring 是不负责销毁的。

不同 Bean 之间的销毁顺序又是怎么样的呢?文档 里说,如果 Bean X 依赖 Bean Y,创建时是 Bean Y 先创建,销毁时则是反过来,Bean X 先销毁。

附加题:如何等待所有 Bean 初始化完成?

有时候我们需要在所有 Bean 都初始化后做一些操作,要怎么做?上面提到的机制都是在单个 Bean 中完成,无法顾及多个 Bean 之间的操作。这时可以利用 ApplicationContextEvent 机制

ApplicationContext 初始化完成或刷新时,会发送 ContextRefreshedEvent 事件,我们只需要让某个 Bean 监听该事件即可。当然要注意这个事件可能会被发送多次(因为刷新时也会再发送该事件),需要酌情忽略后续事件。监听示例代码如下:

@Service
public class InitService {
private final List<InitBean> beansToInitialize;

@Autowired(required = false)
public InitService(List<InitBean> beansToInitialize) {
this.beansToInitialize = beansToInitialize;
}

@EventListener(ContextRefreshedEvent.class)
public void onApplicationEvent(ContextRefreshedEvent event) {
event.getApplicationContext().getBean(InitService.class).initialize();
}

private void initialize() {
beansToInitialize.forEach(InitBean::init);
}
}

参考