Spring之Bean的生命周期
一.Bean的生命周期:
实例化bean之前:InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation
(1)实例化Bean:
对于BeanFactory容器,当客户向容器请求一个尚未初始化的bean时,或初始化bean的时候需要注入另一个尚未初始化的依赖时,容器就会调用createBean进行实例化。对于ApplicationContext容器,当容器启动结束后,通过获取BeanDefinition对象中的信息,实例化所有的bean。具体实现代码
AbstractAutowireCapableBeanFactory.createBeanInstance
(2)设置对象属性(依赖注入):
实例化后的对象被封装在BeanWrapper对象中,紧接着,Spring根据BeanDefinition中的信息 以及 通过BeanWrapper提供的设置属性的接口完成依赖注入。
AbstractAutowireCapableBeanFactory.populateBean
(3)处理Aware接口:
接着,Spring会检测该对象是否实现了xxxAware接口,并将相关的xxxAware实例注入给Bean:
①如果这个Bean已经实现了BeanNameAware接口,会调用它实现的setBeanName(String beanId)方法,此处传递的就是Spring配置文件中Bean的id值;
②如果这个Bean已经实现了BeanFactoryAware接口,会调用它实现的setBeanFactory()方法,传递的是Spring工厂自身。
③如果这个Bean已经实现了ApplicationContextAware接口,会调用setApplicationContext(ApplicationContext)方法,传入Spring上下文;
AbstractAutowireCapableBeanFactory.initializeBean.invokeAwareMethods
(4)BeanPostProcessor:before
如果想对Bean进行一些自定义的处理,那么可以让Bean实现了BeanPostProcessor接口,那将会调用postProcessBeforeInitialization(Object obj, String s)方法。
AbstractAutowireCapableBeanFactory.initializeBean.applyBeanPostProcessorsBeforeInitialization
(5)InitializingBean 与 init-method:
如果Bean在Spring配置文件中配置了 init-method 属性,则会自动调用其配置的初始化方法。
AbstractAutowireCapableBeanFactory.initializeBean.invokeInitMethods
//调用实现了InitializingBean接口的afterPropertiesSet 方法
InitializingBean.afterPropertiesSet
//调用用户自定义的 init-method 方法
invokeCustomInitMethod
(6)如果这个Bean实现了BeanPostProcessor接口:after
将会调用postProcessAfterInitialization(Object obj, String s)方法;由于这个方法是在Bean初始化结束时调用的,所以可以被应用于内存或缓存技术;
AbstractAutowireCapableBeanFactory.initializeBean.applyBeanPostProcessorsAfterInitialization
以上几个步骤完成后,Bean就已经被正确创建了,之后就可以使用这个Bean了。
(7)DisposableBean:
当Bean不再需要时,会经过清理阶段,如果Bean实现了DisposableBean这个接口,会调用其实现的destroy()方法;
AbstractApplicationContext.registerShutdownHook.destroyBeans
(8)destroy-method:
最后,如果这个Bean的Spring配置中配置了destroy-method属性,会自动调用其配置的销毁方法。
BeanFactory中Bean的生命周期
ApplicationContext中Bean的生命周期
BeanFactory
主要逻辑都在doCreate()方法中,逻辑很清晰,就是顺序调用以下三个方法,这三个方法与三个生命周期阶段一一对应,非常重要,在后续扩展接口分析中也会涉及。
- createBeanInstance() -> 实例化
- populateBean() -> 属性赋值
- initializeBean() -> 初始化
源码如下,只列了关键代码,便于理解:
//AbstractAutowireCapableBeanFactory
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { //1 创建bean 实例化阶段 =创建一个bean 对象 instanceWrapper = this.createBeanInstance(beanName, mbd, args); } Object exposedObject = bean; try { //2 属性赋值阶段 this.populateBean(beanName, mbd, instanceWrapper); //3 初始化阶段 exposedObject = this.initializeBean(beanName, exposedObject, mbd); } catch (Throwable var18) { if (var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) { throw (BeanCreationException)var18; } throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18); } }
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
//JDK的安全机制验证权限
if (System.getSecurityManager() != null) {
//实现PrivilegedAction接口的匿名内部类
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
//为Bean实例对象包装相关属性,如名称,类加载器,所属容器等信息
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
//对BeanPostProcessor后置处理器的postProcessBeforeInitialization
//回调方法的调用,为Bean实例初始化前做一些处理
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
//调用Bean实例对象初始化的方法,这个初始化方法是在Spring Bean定义配置
//文件中通过init-method属性指定的
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
//对BeanPostProcessor后置处理器的postProcessAfterInitialization
//回调方法的调用,为Bean实例初始化之后做一些处理
//aop 入口生成代理对象
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
至于销毁,是在容器关闭时调用的,先销毁Bean,再销毁容器,详见ConfigurableApplicationContext#close()
1 protected void doClose() { 2 if (this.active.get() && this.closed.compareAndSet(false, true)) { 3 if (this.logger.isInfoEnabled()) { 4 this.logger.info("Closing " + this); 5 } 6 7 LiveBeansView.unregisterApplicationContext(this); 8 9 try { 10 this.publishEvent((ApplicationEvent)(new ContextClosedEvent(this))); 11 } catch (Throwable var3) { 12 this.logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", var3); 13 } 14 15 if (this.lifecycleProcessor != null) { 16 try { 17 this.lifecycleProcessor.onClose(); 18 } catch (Throwable var2) { 19 this.logger.warn("Exception thrown from LifecycleProcessor on context close", var2); 20 } 21 } 22 //将bean 从map中remove掉 23 this.destroyBeans();
//DefaultListableBeanFactory ,将bean置为null 24 this.closeBeanFactory(); 25 this.onClose(); 26 this.active.set(false); 27 } 28 29 }
二.常用接口
- BeanPostProcessor
- InstantiationAwareBeanPostProcessor
- InitializingBean
三.BeanPostProcessors执行顺序
BeanPostProcessor有很多个,而且每个BeanPostProcessor都影响多个Bean,其执行顺序至关重要,必须能够控制其执行顺序才行。关于执行顺序这里需要引入两个排序相关的接口:PriorityOrdered、Ordered
-
PriorityOrdered首先被执行,PriorityOrdered之间通过接口返回值排序
-
Ordered然后执行,Ordered之间通过接口返回值排序
-
都没有实现PriorityOrdered或者Ordered的是最后执行
根据排序接口返回值排序,默认升序排序,返回值越低优先级越高。
BeanFactoryPostProcess,Bean工厂前置处理器
实例化对象之前
这个机制允许我们在实例化相应对象之前对注册到容器中的BeanDefinition的存储信息进行修改。可以根据这个机制对Bean增加其它信息。修改Bean定义的某些属性值。
想自定义前置处理器需要实现BeanFactoryPostProcess接口。当一个容器存在多种前置处理的时候,可以让前置处理器的实现类同时继承Ordered接口。
Spring容器提供了数种现成的前置处理器,常见的如:
- PropertyPlaceholderConfigurer:允许在xml文件中使用占位符。将占位符代表的资源单独配置到简单的Properties文件中加载
- PropertyOverrideConfigurer:不同于PropertyPlaceholderConfigurer的是,该类用于处理容器中的默认值覆为新值的场景
- CustomEditorConfigurer:此前的两个前置处理器处理的均是BeanDefinition.通过把BeanDefinition的数据修改达到目的。CustomEditorConfigurer没有对BeanDefinition做任何变动。负责的是将后期会用到的信息注册到容器之中。例如将类型转换器注册到BeanDefinition中。供BeanDefinition将获取到的String类型参数转换为需要的类型。
BeanPostProcess:before作用,bean前置处理器
BeanPostProcess:after作用
代理,事务等通过后置处理器实现,创建代理对象