当使用者通过调用BeanFactory#getBean(java.lang.String)会获取到Bean实例;
那么Bean实例是在容器哪个时机创建的?
这里以AnnotationConfigApplicationContext解析配置类(@Configuration)作为分析BeanDefinition加载为例;
在AbstractApplicationContext#refresh中会调用AbstractApplicationContext#invokeBeanFactoryPostProcessors
在前面分析了在AbstractApplicationContext#invokeBeanFactoryPostProcessors方法执行期间会创建BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor两个后置处理器,并将所有的beanDefinition加载到IOC容器;
其中BeanDefinitionRegistryPostProcessor它的执行时机为所有的bean定义信息(BeanDefinition)将要被加载到容器的时候,BeanFactoryPostProcesso它的执行时机是在所有的bean定义信息已经加载到容器的时候;
当beanDefinition被容器加载完后,AbstractApplicationContext#refresh会调用AbstractApplicationContext#finishBeanFactoryInitialization方法用于将剩余的非懒加载单例Bean实例化;
AbstractApplicationContext#finishBeanFactoryInitialization这方法里面有一个beanFactory.preInstantiateSingletons()方法的调用,用于初始化所有的非懒加载的单例Bean;
DefaultListableBeanFactory#preInstantiateSingletons
首先会先获取容器中所有beanDefinition的beanName,需要根据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总体的大致流程图如下: