SpringBean的生命周期
Last updated
Last updated
对于普通的java对象,当new的时候创建对象,当它没有任何引用的时候被垃圾回收机制回收。而Spring Ioc容器托管的对象,它们的生命周期完全由容器控制。Spring Bean的声明周期如下:
整个生命周期流程如下:
Spring对Bean进行初始化 (此时执行构造器)
Spring将值和Bean的引用注入Bean对应的属性中
如果Bean实现了BeanNameAware接口,Spring将Bean的ID传递给setBeanName(String name)方法 (实现BeanNameAware清主要是为了通过Bean的引用来获得Bean的ID,一般业务中是很少有用到Bean的ID的)
如果Bean实现了BeanFactoryAware接口,Spring将调用setBeanFactory方法并把BeanFactory容器实例作为参数传入。 (实现BeanFactoryAware 主要目的是为了获取Spring容器,如Bean通过Spring容器发布事件等)
如果Bean实现了ApplicationContextAware接口,Spring容器将调用setApplicationContext(ApplicationContext ctx)方法,把应用上下文作为参数传入。 (作用与BeanFactory类似都是为了获取Spring容器,不同的是ApplicationContextAware继承自BeanFactory,所以除了BeanFactory的所有功能,还提供了很多其他强大功能 )
当经过上述几个步骤后,bean对象已经被正确构造,但如果你想要对象被使用前再进行一些自定义的处理,就可以通过BeanPostProcessor接口实现。 注意:这个接口作用于所有的Bean 该接口提供了两个函数:
postProcessBeforeInitialzation( Object bean, String beanName ) 当前正在初始化的bean对象会被传递进来,我们就可以对这个bean作任何处理。 这个函数会先于InitialzationBean执行,因此称为前置处理。 所有Aware接口的注入就是在这一步完成的。
postProcessAfterInitialzation( Object bean, String beanName ) 当前正在初始化的bean对象会被传递进来,我们就可以对这个bean作任何处理。 这个函数会在InitialzationBean完成后执行,因此称为后置处理。
当BeanPostProcessor的前置处理完成后就会进入InitializingBean接口。
这一阶段也可以在bean正式构造完成前增加我们自定义的逻辑,但它与前置处理不同,由于该函数并不会把当前bean对象传进来,因此在这一步没办法处理对象本身,只能增加一些额外的逻辑。 若要使用它,我们需要让bean实现该接口,并把要增加的逻辑写在该函数中。然后Spring会在前置处理完成后检测当前bean是否实现了该接口,并执行afterPropertiesSet函数。
当然,Spring为了降低对客户代码的侵入性,给bean的配置提供了init-method属性,该属性指定了在这一阶段需要执行的函数名。Spring便会在初始化阶段执行我们设置的函数。init-method本质上仍然使用了InitializingBean接口。
经过以上的工作后,Bean将一直驻留在应用上下文中给应用使用,直到应用上下文被销毁
如果Bean实现了DisposableBean接口,Spring将调用它的destory方法,作用与在配置文件中对Bean使用destory-method属性的作用一样,都是在Bean实例销毁前执行的方法。
BeanFactoryPostProcessor与BeanPostProcessor不同的是:
BeanFactoryPostProcessor在所有Bean初始化之前执行,也就是最开始的地方;
BeanFactoryPostProcessor只执行一次,而BeanPostProcessor在每个Bean生成周期期间都会执行;
BeanFactoryPostProcessor可以对Bean的配置元数据(XML中配置的bean的属性)进行处理。如果你需要在所有Bean初始化之前执行一段逻辑并且只执行一次,选择BeanFactoryPostProcessor在合适不过了。
使用示例:
SmartLifecycle 在容器所有bean加载和初始化完毕执行。
有时候我们需要在Spring加载和初始化所有bean后,接着执行一些任务或者启动需要的异步服务,这样我们可以使用 SmartLifecycle 来做到。SmartLifecycle 是一个接口。当Spring容器加载所有bean并完成初始化之后,会接着回调实现该接口的类中对应的方法(start()方法)。除了start方法,其他方法的作用如下:
参考:https://www.zhihu.com/question/38597960