本文基于 SpringBoot5.1.8.RELEASE 版本源码解析
Spring IOC源码解析(1)
Spring IOC源码解析(2)
Spring拓展点及调用顺序总结
目录
1. 图例解释说明
1. 循环依赖流程图
- 说明1:我们从“开始创建bean”开始查看此图,先沿着蓝色线条查看全图,蓝色线条表示的是单例模式的处理方式
- 说明2:旁边的缓存图,表示但是存放缓存的情况。
- 说明3:虚线表示获取到bean,直接返回;灰色框表示正常无循环依赖情况不会流入的流程。
- 说明4:流程框中的序号1.1,1.2,1.3对应文中源码的序号,表示同一个方法体内的操作,可以对照源码阅读理解。
2. 举例说明上图
背景:都是单例bean。假如bean A 依赖 B;B依赖A。
- 先创建A:第一次创建A;A在1.1中的缓存都找不到,所有缓存都是空。
- 实例化A:实例化A完成;1.3中把A放入了三级缓存。
- 初始化A:属性赋值,发现A依赖了B;沿图中红线,查找创建B。
- 创建B:第一次创建B;B在1.1中的缓存找不到,所有缓存B都是空。
- 实例化B:实例化B完成;1.3中把B放入三级缓存。
- 初始化B:属性赋值,发现B依赖了A;沿着图中红线,查找A。
- A在三级缓存中已经存在;1.1.3.1 把A放入到二级缓存,并把A从三级缓存中删除,返回A。
- 初始化B中获取到A之后,把A注入到B的依赖属性中。
- 初始化B完成:1.2.2,1.2.3 把B放入到一级缓存,并把B从三级缓存中删除,返回B。
- 初始化A中获取到B,把B注入到A的依赖属性中。
- 初始化A完成:1.2.2,1.2.3 把B放入到一级缓存,并把A从三级缓存中删除,返回A。
2. 源码解析
我们前面进行Spring IOC的源码解析,现在我们就直接看看创建Bean的过程中,循环依赖相关的代码。
1. AbstractBeanFactory.doGetBean
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
//省略代码...
// 获取Bean,如果该Bean存在于缓存中,就返回;如果不存在,返回null(重点关注一下)
Object sharedInstance = getSingleton(beanName);
//省略代码...
// Create bean instance.创建bean实例(重点关注一下)
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
//如果是原型模式,则没取缓存,直接创建新的bean
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
prototypeInstance = createBean(beanName, mbd, args);
}
else {
}
//省略代码...
return (T) bean;
}
1.1 getSingleton(beanName) (DefaultSingletonBeanRegistry)(这个我们重点关注)
我们首先重点看看DefaultSingletonBeanRegistry中的几个属性,表达什么含义;再看看getSingleton方法。
/** Cache of singleton objects: bean name to bean instance. 一级缓存,<beanname, beanInstance>,此处的bean已经完成属性注入*/
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/** Cache of early singleton objects: bean name to bean instance.二级缓存,<beanname, beanInstance>,此处bean已经创建,但没有注入属性*/
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
/** Cache of singleton factories: bean name to ObjectFactory. 三级缓存,<beanname, beanFactory>,beanFactory中的bean已经实例化,没有填充属性*/
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
/** Set of registered singletons, containing the bean names in registration order. 注册的bean,按顺序保存*/
private final Set<String> registeredSingletons = new LinkedHashSet<>(256);
/** Names of beans that are currently in creation. 正在创建的Bean*/
private final Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//从一级缓存中找
Object singletonObject = this.singletonObjects.get(beanName);
//从一级缓存没有找到已经初始化的Bean,且该Bean目前正在创建(也就是说一级缓存找到了Bean直接返回,或者该bean没有初始化且目前不在创建)
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
//从二级缓存中获取Bean
singletonObject = this.earlySingletonObjects.get(beanName);
//二级缓存中没有找到已经创建的Bean,且allowEarlyReference=true(是否允许从三级缓存获取Bean)
if (singletonObject == null && allowEarlyReference) {
//从三级缓存中获取bean工厂
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
//通过Bean工厂创建bean,然后把bean放入到二级缓存,并且从三级缓存中移除
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
1.2 DefaultSingletonBeanRegistry.getSingleton
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
synchronized (this.singletonObjects) {
//从一级缓存中拿,如果一级缓存中,存在,则直接返回,无需创建
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException();
}
//加入到singletonsCurrentlyInCreation,表示正在创建,代码见下面
beforeSingletonCreation(beanName);
try {
//通过工厂创建bean,(函数式编程,就是调用外面的createBean方法)
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
finally {
创建bean完成,把beanname从singletonsCurrentlyInCreation移除,代码如下
afterSingletonCreation(beanName);
}
if (newSingleton) {
//创建完bean,操作缓存,代码如下
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
protected void beforeSingletonCreation(String beanName) {
//把当前beanname加入到singletonsCurrentlyInCreation,表示正在创建
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}
protected void afterSingletonCreation(String beanName) {
//创建bean完成,把beanname从singletonsCurrentlyInCreation移除
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
}
}
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
//添加到一级缓存
this.singletonObjects.put(beanName, singletonObject);
//从三级缓存删除
this.singletonFactories.remove(beanName);
//从二级缓存删除
this.earlySingletonObjects.remove(beanName);
//注册bean完成
this.registeredSingletons.add(beanName);
}
}
1.3 我们再看看创建Bean的过程: AbstractAutowireCapableBeanFactory.doCreateBean
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
//省略代码 ...
//是否单例 && 是否允许循环引用 && 是否正常创建Bean
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
// 如果是,则把beanName对应的工厂放入到三级缓存,而工厂中的bean已经实例化了,但没有初始化。
// 把此处的函数式表达式作为工厂操作方法以便后续调用;
// 移除二级缓存;我们看看里面代码(见下面)
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
//上述已经实例化的bean,下面代码循环引用判断有用
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
//初始化回调之后,bean改变了,exposedObject重新赋值
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
//和上面的值相同
if (earlySingletonExposure) {
//获取二级缓存中的bean,我们看看下面代码,注意此处的false。此处一般返回的是false,因为上面没有放入二级缓存。
//但是如果有其他地方获取了该bean,回到1.1,就会把bean放入到二级缓存,此时二级缓存bean就存在了
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
//如果二级缓存中的bean,和初始化完成的bean一致,没有发生改变。
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
//是否允许上面放入三级缓存的bean和初始化的bean不一致 (默认是false);如果不一致抛异常
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException();
}
}
}
}
return exposedObject;
}
DefaultSingletonBeanRegistry
//此次singletonFactory的参数: getEarlyBeanReference(beanName, mbd, bean),bean是已经实例化了
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
synchronized (this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
//添加到三级缓存
this.singletonFactories.put(beanName, singletonFactory);
//移除二级缓存
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//从一级缓存中拿,拿不到
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
//从二级缓存中拿,返回
singletonObject = this.earlySingletonObjects.get(beanName);
//此处一定为false,因为allowEarlyReference传进来是false
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
3. 总结几个结论和问题
-
只有单例的bean才有缓存,才能解决循环依赖问题;原型bean或其他bean没有使用缓存,每次都是创建新的bean。
-
如果依赖构造函数循环依赖,会报错;因为我们缓存是缓存的实例化完成的bean,没有实例化成功的无法缓存。
-
使用懒加载方式可以解决循环依赖,因为IOC容器启动时,懒加载的bean不会实例化。