AbstractApplicationContext#finishBeanFactoryInitialization总体流程分析

当使用者通过调用BeanFactory#getBean(java.lang.String)会获取到Bean实例;

那么Bean实例是在容器哪个时机创建的?

这里以AnnotationConfigApplicationContext解析配置类(@Configuration)作为分析BeanDefinition加载为例

AbstractApplicationContext#refresh中会调用AbstractApplicationContext#invokeBeanFactoryPostProcessors

在前面分析了在AbstractApplicationContext#invokeBeanFactoryPostProcessors方法执行期间会创建BeanDefinitionRegistryPostProcessorBeanFactoryPostProcessor两个后置处理器,并将所有的beanDefinition加载到IOC容器;

其中BeanDefinitionRegistryPostProcessor它的执行时机为所有的bean定义信息(BeanDefinition)将要被加载到容器的时候,BeanFactoryPostProcesso它的执行时机是在所有的bean定义信息已经加载到容器的时候;

当beanDefinition被容器加载完后,AbstractApplicationContext#refresh会调用AbstractApplicationContext#finishBeanFactoryInitialization方法用于将剩余的非懒加载单例Bean实例化

AbstractApplicationContext#finishBeanFactoryInitialization这方法里面有一个beanFactory.preInstantiateSingletons()方法的调用,用于初始化所有的非懒加载的单例Bean;

DefaultListableBeanFactory#preInstantiateSingletons

首先会先获取容器中所有beanDefinitionbeanName,需要根据beanName实例化Bean;

根据beanDefinition判断是不是抽象的,且不是单例的,且不是懒加载的,在beanDefinition符合条件之后再判断beanName是否为FactoryBean类型,根据不同的条件,调用AbstractBeanFactory#getBean(java.lang.String)的入参也不同,如果beanName是FactoryBean类型的,调用AbstractBeanFactory#getBean(java.lang.String)的入参为:前缀&符号 + beanName;而beanName不是FactoryBean类型的,则将直接传入;

AbstractBeanFactory#getBean该方法是一个空壳方法,没有任何的实现逻辑 真正的逻辑调用在doGetBean()中,该接口是实现了BeanFactory的getBean(String name)接口,这里调用链过于复杂,单独分析;

最后所有实现了SmartInitializingSingleton接口的Bean会回调SmartInitializingSingleton#afterSingletonsInstantiated方法;

从上面的流程也可以看出,它的触发时机是在BeanFactory引导期间的单例Bean实例化例结束时触发的回调接口; 

SmartInitializingSingleton

从某种程度来说, SmartInitializingSingleton接口可以是可以替代InitializatingBean的,但是两者的触发时机不同;InitializatingBean先于SmartInitializingSingleton执行;

AbstractApplicationContext#finishBeanFactoryInitialization总体的大致流程图如下:

 

原文地址:https://www.cnblogs.com/coder-zyc/p/15302877.html