概述
上面的图大概画了整个bean的创建流程,spring在创建bean之前首先从缓存池中去getBean,当从缓存池中获取不到bean时,才会去创建bean。了解spring源码的同学知道,spring中有三级缓存:
- 一级缓存:singletonObjects —> 存放完整bean的单例池
- 二级缓存:earlySingletonObjects —> 存放非完整bean的单例池,存放早期暴露的bean
- 三级缓存:singletonFactories —> 存放可以创建bean的factory,这里的factory主要是去创建bean的
代理对象
在创建bean的过程中,会通过bean后置处理去拿到bean的构造方法,对bean进行创建,然后对bean进行包装代理,如果bean不需要进行包装代理,就会返回一个早期暴露的对象,并放入二级缓存中,如果需要进行包装代理,就会返回一个factory,并放入三级缓存中。
然后会组装bean,这个过程就是去装配bean的属性,当bean装配完成后,bean就算是一个完整的bean了,最后会把这个完整的bean放入单例池中,即一级缓存中。
这就是bean创建的整个过程,这里概述了一下,也是想读到这篇文章的同学心里有一个大概,后面不至于晕乎乎的,下面就进入源码阅读阶段吧。
2.从缓存池中getBean
我们直接看doGetBean()这个方法,方法路径:AbstractBeanFactory#doGetBean(),在该方法最开始的时候就是去从单例池获取bean:
接下来就点进这个方法看看是怎么从缓存中获取bean的:
可以看到代码中,首先是从一级缓存中去拿bean,当拿不到bean时,且当前bean正在被创建,就会从二级缓存中去获取,当二级拿不到时,从三级缓存中获取factory对象,如果拿到了factory对象,会从factory中去获取bean,最后将该bean放入二级缓存中。
由于spring工程在启动时,缓存里肯定没有bean对象,于是就需要去创建bean,接下来看bean是如何创建的。
3.bean的创建
还是doGetBean()方法,看一下最重要的代码片段:
这里有两个方法,先看方法1,即createBean(beanName, mbd, args);点进这个方法去看看,这里省略了一些不重要的代码:
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
//... ...
// Prepare method overrides.
try {
/**
* 处理lookup-Method 和replace-Method,统称为overrides
*/
mbdToUse.prepareMethodOverrides();
}
//... ...
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
/**
* 里面有个后置处理器,如果这个后置处理器能返回一个bean,就直接返回了,不再进行后面的装配,不理会里面的依赖
* InstantiationAwareBeanPostProcessor
*/
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null)