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

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

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

 

AbstractApplicationContext#refresh中会调用AbstractApplicationContext#invokeBeanFactoryPostProcessors

AbstractApplicationContext#finishBeanFactoryInitialization总体流程分析

 

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

BeanDefinitionRegistryPostProcessor继承于BeanFactoryPostProcessor,如下;

AbstractApplicationContext#finishBeanFactoryInitialization总体流程分析

 

BeanDefinitionRegistryPostProcessor是针对于BeanDefinition的操作,BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry的入参是BeanDefinitionRegistry,而BeanDefinitionRegistry提供了对BeanDefinition增删改差操作的接口,通过BeanDefinitionRegistry可以间接地操作BeanDefinition,此时所有的bean定义信息(BeanDefinition)将要被加载到容器;

AbstractApplicationContext#finishBeanFactoryInitialization总体流程分析

 

AbstractApplicationContext#finishBeanFactoryInitialization总体流程分析

 

BeanFactoryPostProcessor是针对于BeanFactory的操作,BeanFactoryPostProcessor#postProcessBeanFactory的入参是ConfigurableListableBeanFactoryConfigurableListableBeanFactory继承于BeanFactory,具有BeanFactory的所有接口功能,而ConfigurableListableBeanFactory能够获取BeanDefinition,此时所有的bean定义信息已经加载到容器,从而能对BeanDefinition进行修改;

AbstractApplicationContext#finishBeanFactoryInitialization总体流程分析

 

AbstractApplicationContext#finishBeanFactoryInitialization总体流程分析

 

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

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

AbstractApplicationContext#finishBeanFactoryInitialization总体流程分析

 

DefaultListableBeanFactory#preInstantiateSingletons

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

AbstractApplicationContext#finishBeanFactoryInitialization总体流程分析

 

根据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)接口,这里调用链过于复杂,单独分析;

AbstractApplicationContext#finishBeanFactoryInitialization总体流程分析

 

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

AbstractApplicationContext#finishBeanFactoryInitialization总体流程分析

 

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

SmartInitializingSingleton

AbstractApplicationContext#finishBeanFactoryInitialization总体流程分析

 

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

 

AbstractApplicationContext#finishBeanFactoryInitialization总体的大致流程图

 AbstractApplicationContext#finishBeanFactoryInitialization总体流程分析

相关文章:

  • 2021-06-26
  • 2021-11-09
  • 2021-05-18
  • 2021-12-04
  • 2021-09-06
  • 2022-01-12
  • 2022-03-09
  • 2021-07-31
猜你喜欢
  • 2021-11-24
  • 2021-11-18
  • 2021-05-21
  • 2021-08-02
  • 2021-11-18
  • 2022-01-07
相关资源
相似解决方案