4.5 Bean的生命周期
面试必问的问题
- bean的生命周期
- bean的生命周期由谁管理
- 单例和原型模式下生命周期的区别
4.5.1 BeanFactory中Bean的生命周期
BeanFactory是一个接口,这里BeanFactory生命周期的分析是和下面的ApplicationContext的生命周期相对应的。
很长,不想看。按照Bean对象的行为可以用这三个时间点切分:1、Bean对象创建 2、Bean对象属性注入 3、Bean对象销毁
中所周期BeanFactory采用懒加载机制,Bean只有在第一次使用的时候才被创建。在Bean对象创建前,如果容器里注册了实现InstantiationAwareBeanPostProcessor接口的类,那么在Bean创建前会执行postProcessBeforeInstantiation方法。这个接口的名字有点奇怪,BeanPostProcessor好像是在Bean被创建之后才调用的方法但明明有一个是Bean创建前调用的方法。
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor { Object postProcessBeforeInstantiation(Class<?> var1, String var2) throws BeansException; boolean postProcessAfterInstantiation(Object var1, String var2) throws BeansException; PropertyValues postProcessPropertyValues(PropertyValues var1, PropertyDescriptor[] var2, Object var3, String var4) throws BeansException; }
在为Bean注入属性之前,还要执行上面这个接口的postProcessAfterInstantiation方法。这个名字就比较合适了,After Befor很清晰。这个接口最后一个方法postProcessPropertyValues是在设置每个属性之前调用的。这个接口的全家桶在设置属性前会被全部调用,然后会为Bean设置属性值。
走到这里Bean已经被创建好且初始化完毕了,剩下的内容是针对Bean实现了特定的接口做出的特殊的处理,InstantiationAwareBeanPostProcessor全家桶是注册在容器里的,可以理解为全部的Bean初始化都要走InstantiationAwareBeanPostProcessor的逻辑。
首先是BeanXXXXAware接口,实现了BeanNameAware接口的Bean能知道自己在Bean容器的名字,实现了BeanFactoryAware接口的Bean能够获得BeanFactory实例。
接下来是BeanPostProcessor全家桶,这个名字和注册在容器里的InstantiationAwareBeanPostProcessor名字很像,InstantiationAwareBeanPostProcessor是BeanPostProcessor的子接口。首先调用的是BeforXXXX的方法,这个方法用于改变Bean对象,即在Bean对象被初始化完成属性注入完成后我们依然可以有机会改变他,Object var1就是需要改变的Bean对象,返回的是改变后的Bean对象,大名鼎鼎的Aop就是在这里实现的。在执行AfterXXX之前,如果Bean实现了initalizingBean接口则调用afterPropertiesSert。如果在配置文件里配置了init-method方法则会执行方法注入。然后就调用postProcessAfterInitialization方法。
public interface BeanPostProcessor { Object postProcessBeforeInitialization(Object var1, String var2) throws BeansException; Object postProcessAfterInitialization(Object var1, String var2) throws BeansException; }
到这里所有可以实现的接口、所有特殊的注入都检查完毕了。如果scope是singleton,就把bean放到缓存里,然后返回给调用者;如果是prototype就直接返回给调用者,Spring不在负责prototype的Bean的声明管理。
容器只会负责singleton的Bean的后续生命管理,体现在两个地方,在容器关闭的时候,如果Bean实现了DisposableBean接口那么调用的destory方法;如果在xml里配置了destory-method属性则调用该方法。