从源码分析Spring的生命周期

400 阅读2分钟

前言

  • Spring 中 Bean 的生命周期从容器的启动到停止,涉及到的源码主要是在`org.springframework.context.support.AbstractApplicationContext.refresh`方法中,下面也是围绕其中的逻辑进行讲解。

开撸

【1】 prepareRefresh()

内部其实很简单,就是设置一些标志,比如开始时间,激活的状态等。

【2】prepareBeanFactory(beanFactory)

做一些简单的准备工作,此处不再赘述!!!

【3】postProcessBeanFactory(beanFactory)

主要的作用就是添加了一个后置处理器ServletContextAwareProcessor

【4】invokeBeanFactoryPostProcessors(beanFactory)

调用容器中的所有的BeanFactoryPostProcessor中的postProcessBeanFactory方法,按照优先级调用,主要实现逻辑在 invokeBeanFactoryPostProcessors()

  1. 执行所有 BeanDefinitionRegistryPostProcessor(对 BeanFactoryPostProcessor 的扩展,运行在普通的实现类之前注册 bean)的方法,同样是内部按照优先级进行排序调用
  2. 对剩余的进行按照优先级排序调用,同样是内部进行排序执行

【5】registerBeanPostProcessors(beanFactory)

注册所有的BeanPostProcessor(后置处理器),按照优先级注册,分别是 PriorityOrdered,Ordered,普通的,内部的。主要的实现逻辑在 PostProcessorRegistrationDelegate.registerBeanPostProcessors()

【6】initMessageSource() 注册 MessageSource,提供消息国际化等功能

【7】initApplicationEventMulticaster();

注册事件广播器 ApplicationEventMulticaster,用于 spring 事件的广播和事件监听器的处理

【8】registerListeners()

注册事件监听器 ApplicationListener,并且广播一些早期的事件,主要的逻辑在 org.springframework.context.support.AbstractApplicationContext.registerListeners

【9】finishBeanFactoryInitialization(beanFactory)

实例化所有非懒加载的 Bean,spring 生命周期中的主要方法,主要逻辑在 org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons,深入进去其实就是 getBean()方法创建,详情向下看。

【10】finishRefresh()

主要的功能是发布事件 ContextRefreshedEvent

【11】destroyBeans()

容器启动出现异常时销毁 Bean

以上就是 Spring 容器启动的过程,主要的逻辑都在 org.springframework.context.support.AbstractApplicationContext#refresh 中,其他的都很容易理解,现在我们着重分析一下单例 Bean 的创建过程,入口是第 9 步。

实例化单例 Bean

【1】debug 进入,实际主要的逻辑都在 org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons 方法中,逻辑如下:

//获取所有注入到ioc容器中的bean定义信息
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
  //循环创建
  for (String beanName : beanNames) {
   RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
            //非抽象,单例,非懒加载的bean初始化
   if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
                //如果是FactoryBean
    if (isFactoryBean(beanName)) {
                    //getBean
     Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
                    //非FactoryBean,getBean
    else {
     getBean(beanName);
    }
   }
  }

以上源码总结得知,最终实例化 Bean 的方法肯定在 getBean 中的,debug 进入,得知 doGetBean 是大 boss,spring 源码有趣的是最终的实现都是在 doxxxx()。

【2】AbstractBeanFactory#doGetBean,由于篇幅太短,就不贴源码了,只贴关键代码

实例化的主要流程全部都在这里,下面一一解析即可。

(1) Object sharedInstance = getSingleton(beanName)

从早期的缓存中获取,如果存在返回 Bean,实例化

(2)BeanFactory parentBeanFactory = getParentBeanFactory()

从父工厂的中获取 Bean

(3)if (mbd.isSingleton())

分单例和多例进行分开创建 Bean,这里只分析单例 Bean 的创建

(4)sharedInstance = getSingleton(beanName, () -> { try { return createBean(beanName, mbd, args); }

createBean 方法创建 Bean,进入 createBean()

​ a. Object bean = resolveBeforeInstantiation(beanName, mbdToUse):执行所有的 InstantiationAwareBeanPostProcessor 中的postProcessBeforeInstantiation,在实例化之前调用,返回 null 继续下一步,返回一个 bean,那么 bean 实例化完成,将调用其中的postProcessAfterInstantiation方法

​ b. Object beanInstance = doCreateBean(beanName, mbdToUse, args):创建 Bean 的完成过程

​ c. 进入doCreateBean,instanceWrapper = createBeanInstance(beanName, mbd, args):创建 Bean 的实例

​ d. populateBean(beanName, mbd, instanceWrapper):属性装配,执行 InstantiationAwareBeanPostProcessor 的postProcessAfterInstantiation,再执行postProcessProperties方法。

​ e. exposedObject = initializeBean(beanName, exposedObject, mbd):初始化 Bean,debug 进入

​ f. invokeAwareMethods(beanName, bean):调用BeanNameAwareBeanClassLoaderAwareBeanFactoryAware中的对应方法

​ g. wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName):调用 BeanPostProcessord 中的postProcessBeforeInitialization方法

​ h. invokeInitMethods(beanName, wrappedBean, mbd):执行InitializingBean中的afterPropertiesSet

​ i. wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName):调用BeanPostProcessor中的postProcessAfterInitialization方法

总结

以上是 spring 容器从启动到销毁的全部过程,根据源码陈某画了一张生命周期的图,仅供参考,请勿转载!!!

![](https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2020/4/10/171649c6f3486b76~tplv-t2oaga2asx-image.image)