Springbean生命周期之Initializing-Bean

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接口

  • 在bean的定义中自定义init和destroy方法

  • 通过注解@PostConstruct和@PreDestroy


下面这张图描述了整个流程

Springbean生命周期之Initializing-Bean

(图片来源于网络)

接下来,我会分数篇对这些机制做逐一的说明,今天我们的重点是InitializingBean。

这个接口本身其实很简单,让我们想要控制的bean实现这个接口的afterPropertiesSet()方法即可,这个方法执行的时候,bean的属性都已经被装配好,我们可以完成一系列自定义的操作。


举个粟子

  1. 首先定义我们自己的bean

    Springbean生命周期之Initializing-Bean

  2. 在spring-context.xml中配置bean

    Springbean生命周期之Initializing-Bean

  3. 用Junit的方式启动容器

    Springbean生命周期之Initializing-Bean

  4. 然后我们打开Spring的debug log,就能看到如下输出
    Springbean生命周期之Initializing-Bean

    在这个例子里中,只是简单的打印了bean的属性message,可以看到message已经被赋值.


接下来我们来看下InitializingBean源码以及这个流程的Spring内部实现


public interface InitializingBean {

/**
   * Invoked by a BeanFactory after it has set all bean properties supplied
   * (and satisfied BeanFactoryAware and ApplicationContextAware).
   * <p>This method allows the bean instance to perform initialization only
   * possible when all bean properties have been set and to throw an
   * exception in the event of misconfiguration.
   *
@throws Exception in the event of misconfiguration (such
   * as failure to set an essential property) or if initialization fails.
   */
 
void afterPropertiesSet() throws Exception;

我们看他的注释已经说说得很明确了,这个方法用来完成一些特殊的初始化操作,并且是在属性都设置好后才会被beanFactory调用。那么我们来看看有谁用这个接口了

怎么看?如果你用IDEA的话,直接在工程类或者library中查询该方法的实现Find...so much usages

Springbean生命周期之Initializing-Bean

这个接口在Spring底层建筑和一些其它跟spring整合的插件里大量使用,足见这个接口的重要性,浏览这些实现了afterPropertiesSet方法的实现,你会发现各不相同,但总体来说,无非是一些初始化工作,一些重量级的bean在这里完成其复杂的初始化工作。

知其然,也要知其所以然。我们实现了这个接口,就可以完成一些初始化操作,那么是怎么做到的呢,上边InitializingBean的注释里已经明确提到了,这个接口的实现会给BeanFactory调用,但代码中在哪里有体现呢?

查询InitializingBean.afterPropertiesSet()方法的usages

如图 Find usage 

Springbean生命周期之Initializing-Bean

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

Springbean生命周期之Initializing-Bean

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

Springbean生命周期之Initializing-Bean

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

Springbean生命周期之Initializing-Bean

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

Springbean生命周期之Initializing-Bean

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

这就是InitializingBean的机制。




Springbean生命周期之Initializing-Bean

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



发表评论