- 追踪bean初始化时候的源码。在
org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean()处,生成bean的核心方法是createBean(beanName, mbd, args);
// scope是单例--> 创建一个bean的实例对象
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
// 本质是构造器的createInstance()方法创建了对象
return createBean(beanName, mbd, args);
} catch (BeansException ex) {
//从单例缓存中移除实例
//创建过程中,允许循环引用解析。
//同时删除所有接收到临时引用的bean。
destroySingleton(beanName);
throw ex;
}
});
- 创建bean的时候,会去调用一遍
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#Singleton()方法
/**
* 获取单例bean对象
* singletonObjects --> 一级缓存,单例池,也就是通常所说的Spring容器,所有单例的bean都是从中获取对象
* earlySingletonObjects --> 二级缓存,避免一个bean被多个bean依赖,而出现多次调用工厂的情况
* singletonFactories --> 三级缓存,工厂代理,其中包含了生成bean的过程。
* <p>
* 循环依赖过程:
* A <--> B 互相依赖
* ① 创建bean A,创建过程中(标记A正在创建),填充A的属性,发现需要bean B
* ② 创建bean B,创建过程中(标记B正在创建),填充B的属性,发现需要bean A
* ③ 再次通过 getSingleton() 方法去创建A
* ④ 一级缓存(单例池)存在A,则返回,否则走第⑤步
* ⑤ 发现A正在创建中,查看二级缓存,存在||不循序循环依赖则返回,存在&&允许循环依赖则走第⑥步
* ⑥ 三级缓存(生产工厂)获取bean A
* ⑦ 填充bean B-->放入一级缓存
* ⑧ 填充bean A-->放入一级缓存
*
* @param beanName 默认为小写类名
* @param allowEarlyReference 是否允许循环依赖
* @return
*/
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 通过beanName去一级缓存(单例池)中获取对象
Object singletonObject = this.singletonObjects.get(beanName);
// 对象为空 && beanName的这个bean正在创建过程中--
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
// 通过beanName去二级缓存中获取对象
singletonObject = this.earlySingletonObjects.get(beanName);
// 二级缓存不存在对象且 该beanName所对应的beanDefinetion中的allowEarlyReference (支持循环依赖)为true
if (singletonObject == null && allowEarlyReference) {
synchronized (this.singletonObjects) {
// 单例模式-锁双重判断
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
// 二级缓存再去获取一次对象
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
// 最终去三级缓存,工厂中去生成对象
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
// 放入二级缓存
this.earlySingletonObjects.put(beanName, singletonObject);
// 三级缓存移除
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
本文深入探讨Spring框架中Bean的初始化过程,重点分析了单例Bean的创建机制,包括Bean实例化、依赖注入及循环依赖的解决策略。文章详细介绍了如何通过多级缓存机制来实现高效的Bean管理。
3822

被折叠的 条评论
为什么被折叠?



