系统化的学习技术、研究技术而不是使用技术

Spring Bean 的生命周期

2018/12/28 15:59:54 | 浏览(467) | Spring

最近面试的时候被问到 Spring Bean 生命周期,虽然平时都有用到 Spring 框架,但真要说起来却不知道从何说起,这也说明了学习技术不能仅限于使用,而是要去了解技术的原理。给自己敲响一下警钟。

1. 实例化 Bean

对于 BeanFactory 容器,当客户向容器请求一个尚未初始化的 bean 时,或初始化 bean 的时候需要注入另一个尚未初始化的依赖时,容器就会调用 createBean 进行实例化。

对于 ApplicationContext 容器,当容器启动结束后,便实例化所有的 bean。 容器通过获取 BeanDefinition 对象中的信息进行实例化。并且这一步仅仅是简单的实例化,并未进行依赖注入。

实例化对象被包装在 BeanWrapper 对象中,BeanWrapper 提供了设置对象属性的接口,从而避免了使用反射机制设置属性。

2. 设置对象属性(依赖注入)

实例化后的对象被封装在 BeanWrapper 对象中,并且此时对象仍然是一个原生的状态,并没有进行依赖注入。

紧接着,Spring 根据 BeanDefinition 中的信息进行依赖注入。 并且通过 BeanWrapper 提供的设置属性的接口完成依赖注入。

3. 注入 Aware 接口

接下来,Spring 会检测该对象是否实现了 xxxAware 接口,并将相关的 xxxAware 实例注入给 bean。

其中包括

  • BeanNameAware
  • BeanFactoryAware
  • ApplicationContextAware

4. BeanPostProcessor

当经过上述几个步骤后,bean 对象已经被正确构造,但如果你想要对象被使用前再进行一些自定义的处理,就可以通过 BeanPostProcessor 接口实现。

该接口提供了两个函数:

  • postProcessBeforeInitialzation(Object bean, String beanName) 当前正在初始化的 bean 对象会被传递进来,我们就可以对这个 bean 作任何处理。 这个函数会先于 InitialzationBean 执行,因此称为前置处理。所有 Aware 接口的注入就是在这一步完成的。

  • postProcessAfterInitialzation(Object bean, String beanName) 当前正在初始化的 bean 对象会被传递进来,我们就可以对这个 bean 作任何处理。 这个函数会在 InitialzationBean 完成后执行,因此称为后置处理。

BeanPostProcessor 经常被用作是 Bean 内容的更改,并且由于这个是在 Bean 初始化结束时调用那个的方法,也可以被应用于内存或缓存技术。

5. InitializingBean 与 init-method

当 BeanPostProcessor 的前置处理完成后就会进入本阶段。

InitializingBean 接口只有一个函数

  • afterPropertiesSet()

这一阶段也可以在 bean 正式构造完成前增加我们自定义的逻辑,但它与前置处理不同,由于该函数并不会把当前 bean 对象传进来,因此在这一步没办法处理对象本身,只能增加一些额外的逻辑。

若要使用它,我们需要让 bean 实现该接口,并把要增加的逻辑写在该函数中。然后 Spring 会在前置处理完成后检测当前 bean 是否实现了该接口,并执行 afterPropertiesSet 函数。

当然,Spring 为了降低对客户代码的侵入性,给 bean 的配置提供了 init-method 属性,该属性指定了在这一阶段需要执行的函数名。Spring 便会在初始化阶段执行我们设置的函数。init-method 本质上仍然使用了 InitializingBean 接口。

6. DisposableBean 和 destroy-method

和 init-method 一样,通过给 destroy-method 指定函数,就可以在 bean 销毁前执行指定的逻辑。

附图

最后更新于 2018/12/29 09:50:14

留言(1)

九十万禁军教头@2019/01/02 09:10:19

到此一游

给我留言