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()方法中,逻辑很清晰,就是顺序调用以下三个方法,这三个方法与三个生命周期阶段一一对应,非常重要,在后续扩展接口分析中也会涉及。

  1. createBeanInstance() -> 实例化
  2. populateBean() -> 属性赋值
  3. 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作用

代理,事务等通过后置处理器实现,创建代理对象

 

posted @ 2020-05-08 14:32  暖暖-木木  阅读(239)  评论(0编辑  收藏  举报