一、前言
本文是笔者阅读Spring源码的记录文章,由于本人技术水平有限,在文章中难免出现错误,如有发现,感谢各位指正。
在Spring容器的初始化过程后期 通过调用AbstractApplicationContext#finishBeanFactoryInitialization 方法来实例化了所有的非延迟加载bean。在这里面就通过 beanFactory.preInstantiateSingletons(); 调用了一个非常关键的方法 AbstractBeanFactory#getBean(java.lang.String),而其实际上调用的是 AbstractBeanFactory#doGetBean 方法
//获取IOC容器中指定名称的Bean
@Override
public Object getBean(String name) throws BeansException {
//doGetBean才是真正向IoC容器获取被管理Bean的过程
return doGetBean(name, null, null, false);
}
如果说,Spring中,Bean 的发现是在 ConfigurationClassPostProcessor 中进行的。那么Bean的创建就是在 doGetBean方法中进行的。 doGetBean 完成了单例Bean的完整创建过程,包括bean的创建,BeanPostProcessor 的方法调用、init-method等方法的调用、Aware 等接口的实现。
下面,我们开始来分析这个 doGetBean。
关于Bean 的加载过程,AbstractApplicationContext#finishBeanFactoryInitialization 经过几次跳转,最终会跳转到 AbstractBeanFactory#doGetBean 方法。每个bean的创建都会经历此方法,所以本文的主要内容是分析 AbstractBeanFactory#doGetBean 。
二、DefaultListableBeanFactory
需要强调的是,本文中调用 doGetBean
方法的是 AbstractBeanFactory
的子类DefaultListableBeanFactory
。如下图
DefaultListableBeanFactory
结构图如下:
1. DefaultSingletonBeanRegistry
在这里我们只需要知道DefaultListableBeanFactory 继承了 DefaultSingletonBeanRegistry类,拥有了 DefaultSingletonBeanRegistry 一系列的 集合类型来保存Bean相关信息。
/** Cache of singleton objects: bean name to bean instance. */
// 用于保存BeanName和创建bean实例之间的关系,即缓存bean。 beanname -> instance
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/** Cache of singleton factories: bean name to ObjectFactory. */
// 用于保存BeanName和常见bean的工厂之间的关系。beanname-> ObjectFactory
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
/** Cache of early singleton objects: bean name to bean instance. */
// 也是保存BeanName和创建bean实例之间的关系,与singletonObjects 不同的是,如果一个单例bean被保存在此,则当bean还在创建过程中(比如 A类中有B类属性,当创建A类时发现需要先创建B类,这时候Spring又跑去创建B类,A类就会添加到该集合中,表示正在创建),就可以通过getBean方法获取到了,其目的是用来检测循环引用。
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
/** Set of registered singletons, containing the bean names in registration order. */