Spring 作为一个Ioc容器,它的一个重要职责便是对容器中bean的管理。在Spring中默认bean的scope是singleton,所以这在这里讨论的是该类型的不包括其它作用域的bean.
通俗来讲,Spring beans的生命周期无非就是bean在Spring容器中走这一遭,从无到有,再从有到无这个过程经历了哪些步骤。
粗略的可分以下几步
实例化
装配属性
销毁
这一系列过程看似简单,实现起来并不那么容易,如何实例化,如何装配属性,这些机制的实现不得不提BeanFactory以及BeanDefination等核心技术,今天在这里先不讨论这些细节,后续的篇幅中会做详细的代码分析。
Spring beans 在整个生命周期中,如果有业务需要做些特殊的操作或者定制,那么我们该如何做?不用担心,Spring做为一个高度可定制可扩展的框架已经充分考虑了这方面的因素,所以在Spring beans生命周期中,提供了一些列的机制来供我们控制这些bean,接下来就从几个方面来看看这些机制都是什么。
InitializingBean 和 DisposableBean 接口
BeanNameAware、BeanFactoryAware及ApplicationContextAware接口
通过注解@PostConstruct和@PreDestroy
下面这张图描述了整个流程

(图片来源于网络)
接下来,我会分数篇对这些机制做逐一的说明,今天我们的重点是InitializingBean。
这个接口本身其实很简单,让我们想要控制的bean实现这个接口的afterPropertiesSet()方法即可,这个方法执行的时候,bean的属性都已经被装配好,我们可以完成一系列自定义的操作。
举个粟子
首先定义我们自己的bean

在spring-context.xml中配置bean

用Junit的方式启动容器

然后我们打开Spring的debug log,就能看到如下输出
接下来我们来看下InitializingBean源码以及这个流程的Spring内部实现
我们看他的注释已经说说得很明确了,这个方法用来完成一些特殊的初始化操作,并且是在属性都设置好后才会被beanFactory调用。那么我们来看看有谁用这个接口了
怎么看?如果你用IDEA的话,直接在工程类或者library中查询该方法的实现Find…so much usages

这个接口在Spring底层建筑和一些其它跟spring整合的插件里大量使用,足见这个接口的重要性,浏览这些实现了afterPropertiesSet方法的实现,你会发现各不相同,但总体来说,无非是一些初始化工作,一些重量级的bean在这里完成其复杂的初始化工作。
知其然,也要知其所以然。我们实现了这个接口,就可以完成一些初始化操作,那么是怎么做到的呢,上边InitializingBean的注释里已经明确提到了,这个接口的实现会给BeanFactory调用,但代码中在哪里有体现呢?
查询InitializingBean.afterPropertiesSet()方法的usages
如图 Find usage

结果中我们会找到一个BeanFactory的子类,有调用此方法。

方法的源码如下,还是那句话,注释永远是第一手说明

谈到这里我们有一点值得注意,对这个InitializingBean的调用,并不是根BeanFactory的行为(看BeanFactory接口就知道没有这个方法),而是其一个子类添加的行为,直观起见,看上边提到的AbstractAutowireCapableBeanFactory的继续关系图

顺滕摸瓜,我们找到AutowireCaplableBeanFactory中定义了这个行为

也就是说, 在Spring容器启动过程中,beanFactory的实现类通过initializeBean方法对每个实现的InitializingBean的bean调用其afterPropertiesSet方法。
这就是InitializingBean的机制。

欢迎关注,期待与您的交流,让我们携手在通往牛逼的小路上徐徐前行。