getBean源码实战(三)
代码仓库 :Gitee 仓库链接
本文档的所有示例代码都可以在代码仓库中找到,建议结合代码一起阅读。
1. 单例 Bean 的循环依赖处理
1.1 示例 Bean:ServiceA 和 ServiceB
本篇重点分析:当单例 Bean 之间存在循环依赖时,Spring 如何通过三级缓存机制来解决这个问题。
Bean 类定义:
ServiceA:
1:37:spring-source/code/spring-basic/src/main/java/com/example/getbean/ServiceA.java
package com.example.getbean;
/**
* ServiceA,依赖ServiceB
* 用于演示循环依赖的解决
*/
public class ServiceA {
private ServiceB serviceB;
private String name;
public ServiceA() {
System.out.println("ServiceA 构造函数被调用");
}
public ServiceB getServiceB() {
return serviceB;
}
public void setServiceB(ServiceB serviceB) {
System.out.println("ServiceA.setServiceB() 被调用,注入ServiceB");
this.serviceB = serviceB;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void doSomething() {
System.out.println("ServiceA[" + name + "] 执行操作,依赖ServiceB: " +
(serviceB != null ? serviceB.getName() : "null"));
}
}
ServiceB:
1:37:spring-source/code/spring-basic/src/main/java/com/example/getbean/ServiceB.java
package com.example.getbean;
/**
* ServiceB,依赖ServiceA
* 用于演示循环依赖的解决
*/
public class ServiceB {
private ServiceA serviceA;
private String name;
public ServiceB() {
System.out.println("ServiceB 构造函数被调用");
}
public ServiceA getServiceA() {
return serviceA;
}
public void setServiceA(ServiceA serviceA) {
System.out.println("ServiceB.setServiceA() 被调用,注入ServiceA");
this.serviceA = serviceA;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void doSomething() {
System.out.println("ServiceB[" + name + "] 执行操作,依赖ServiceA: " +
(serviceA != null ? serviceA.getName() : "null"));
}
}
XML 配置:
17:26:spring-source/code/spring-basic/src/main/resources/applicationContext-getbean.xml
<!-- 循环依赖示例 -->
<bean id="serviceA" class="com.example.getbean.ServiceA">
<property name="name" value="ServiceA"/>
<property name="serviceB" ref="serviceB"/>
</bean>
<bean id="serviceB" class="com.example.getbean.ServiceB">
<property name="name" value="ServiceB"/>
<property name="serviceA" ref="serviceA"/>
</bean>
1.2 代码仓库位置
- ServiceA 类 :
code/spring-basic/src/main/java/com/example/getbean/ServiceA.java - ServiceB 类 :
code/spring-basic/src/main/java/com/example/getbean/ServiceB.java - 配置文件 :
code/spring-basic/src/main/resources/applicationContext-getbean.xml - 测试类 :
code/spring-basic/src/test/java/com/example/getbean/GetBeanProcessTest.java
1.3 循环依赖说明
循环依赖关系:
ServiceA依赖ServiceB(通过setServiceB()方法注入)ServiceB依赖ServiceA(通过setServiceA()方法注入)- 形成了
ServiceA↔ServiceB的循环依赖
关键点:
- 两个 Bean 都是单例作用域 (默认
scope="singleton") - 使用属性注入 (
<property>标签),而不是构造器注入 - Spring 通过三级缓存机制来解决单例 Bean 的循环依赖问题
1.4 执行流程概述
当我们调用 factory.getBean("serviceA") 时,Spring 会执行以下步骤:
-
开始创建 ServiceA
- 创建
ServiceA实例(调用无参构造方法) - 将
ServiceA的工厂对象放入三级缓存
- 创建
-
填充 ServiceA 的属性
- 发现
ServiceA依赖ServiceB - 调用
getBean("serviceB")获取ServiceB
- 发现
-
开始创建 ServiceB
- 创建
ServiceB实例(调用无参构造方法) - 将
ServiceB的工厂对象放入三级缓存
- 创建
-
填充 ServiceB 的属性
- 发现
ServiceB依赖ServiceA - 从三级缓存中获取
ServiceA的早期引用(提前暴露的对象)
- 发现
-
完成 ServiceB 的创建
ServiceB创建完成,放入一级缓存
-
完成 ServiceA 的创建
- 将
ServiceB注入到ServiceA ServiceA创建完成,放入一级缓存
- 将
核心机制 :Spring 使用三级缓存 (singletonObjects、earlySingletonObjects、singletonFactories)来解决循环依赖问题。
1.5 深入 doGetBean 方法(循环依赖处理流程)
当我们调用 factory.getBean("serviceA") 时,Spring 会进入 AbstractBeanFactory.doGetBean() 方法。由于 ServiceA 和 ServiceB 之间存在循环依赖,整个流程会涉及三级缓存机制。让我们逐步分析这个过程。
核心流程概览:
factory.getBean("serviceA")
↓
doGetBean("serviceA")
↓
getSingleton("serviceA", singletonFactory)
↓
createBean("serviceA", ...) → doCreateBean("serviceA", ...)
↓
1. createBeanInstance() - 创建ServiceA实例
2. 提前暴露到三级缓存
3. populateBean() - 填充属性
↓
发现需要ServiceB → getBean("serviceB")
↓
... ServiceB的创建流程 ...
↓
在populateBean时,从三级缓存获取ServiceA的早期引用
↓
完成ServiceB的创建 → 返回给ServiceA
↓
完成ServiceA的创建
核心流程概览:
factory.getBean("serviceA")
↓
doGetBean("serviceA")
↓
getSingleton("serviceA", singletonFactory)
↓
createBean("serviceA", ...) → doCreateBean("serviceA", ...)
↓
1. createBeanInstance() - 创建ServiceA实例
2. 提前暴露到三级缓存
3. populateBean() - 填充属性
↓
发现需要ServiceB → getBean("serviceB")
↓
... ServiceB的创建流程 ...
↓
在populateBean时,从三级缓存获取ServiceA的早期引用
↓
完成ServiceB的创建 → 返回给ServiceA
↓
完成ServiceA的创建
步骤 1:解析 Bean 名称
源码位置 :AbstractBeanFactory.doGetBean()
java
// AbstractBeanFactory.java
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType,
@Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
// 步骤1:解析Bean名称
final String beanName = transformedBeanName(name);
// ... 后续步骤
}
作用:将传入的 Bean 名称转换为实际的 Bean 名称。
- 对于
"serviceA",由于它不是别名,也不是 FactoryBean 的特殊前缀,所以转换后仍然是"serviceA"。 - 处理逻辑与第一篇、第二篇相同,这里不再赘述。
步骤 2:获取缓存中的单例对象
源码位置 :AbstractBeanFactory.doGetBean()
java
// AbstractBeanFactory.java
protected <T> T doGetBean(...) {
final String beanName = transformedBeanName(name); // "serviceA"
// 步骤2:获取缓存中的单例对象
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
return bean;
}
// ... 后续步骤
}
作用:从单例缓存中尝试获取已存在的 Bean 实例。
处理过程:
- 调用
getSingleton("serviceA")方法 - 此时
ServiceA还未初始化,一级缓存singletonObjects中没有,所以sharedInstance为null - 继续进入创建流程
步骤 3:检查循环依赖(单例作用域)
源码位置 :AbstractBeanFactory.doGetBean()
java
// AbstractBeanFactory.java
protected <T> T doGetBean(...) {
// ... 前面的步骤
// 步骤3:因为是单例Scope,不会检查循环依赖
// 注意:这里的循环依赖检查是针对原型Bean的,单例Bean的循环依赖通过三级缓存机制解决
// if (isPrototypeCurrentlyInCreation(beanName)) {
// throw new BeanCurrentlyInCreationException(beanName);
// }
// ... 后续步骤
}
说明:对于单例 Bean,Spring 不会在这里检查循环依赖,而是通过三级缓存机制来解决。循环依赖检查主要针对原型 Bean,因为原型 Bean 不支持循环依赖。
步骤 4:检查父级 BeanFactory
源码位置 :AbstractBeanFactory.doGetBean()
java
// AbstractBeanFactory.java
protected <T> T doGetBean(...) {
// ... 前面的步骤
// 步骤4:因为没有parentBeanFactory,所以不会走相关逻辑
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// 由父级BeanFactory处理(本次不关注)
}
// ... 后续步骤
}
说明:对于我们的示例,没有配置父级 BeanFactory,所以跳过这个逻辑。
步骤 5:标记 Bean 正在被创建
源码位置 :AbstractBeanFactory.doGetBean()
java
// AbstractBeanFactory.java
protected <T> T doGetBean(...) {
// ... 前面的步骤
// 步骤5:因为是创建实例,所以要标记bean正在被创建
// 这里一会儿应该就能体现循环依赖的作用了
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
// ... 后续步骤
}
作用:标记该 Bean 正在被创建,防止重复创建。
markBeanAsCreated 方法实现:
java
// AbstractBeanFactory.java
protected void markBeanAsCreated(String beanName) {
if (!this.alreadyCreated.contains(beanName)) {
synchronized (this.mergedBeanDefinitions) {
if (!this.alreadyCreated.contains(beanName)) {
// 双检查:确保线程安全
this.alreadyCreated.add(beanName);
// 清理合并后的Bean定义缓存,后续会重新合并
this.mergedBeanDefinitions.remove(beanName);
}
}
}
}
关键点:
- 将
beanName加入alreadyCreated集合,标记 Bean 正在创建 - 这个标记在后续的循环依赖处理中会用到:当
ServiceB需要ServiceA时,会发现ServiceA正在创建中,从而从三级缓存中获取早期引用
步骤 6:ApplicationStartup 处理
源码位置 :AbstractBeanFactory.doGetBean()
java
// AbstractBeanFactory.java
protected <T> T doGetBean(...) {
// ... 前面的步骤
// 步骤6:StartupStep默认没有具体行为(本次不关注)
// StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate");
// ... 后续步骤
}
说明 :默认的 applicationStartup 是 DefaultApplicationStartup,不做任何实际处理,主要用于性能监控。
步骤 7:获取合并后的 Bean 定义
源码位置 :AbstractBeanFactory.doGetBean()
java
// AbstractBeanFactory.java
protected <T> T doGetBean(...) {
// ... 前面的步骤
// 步骤7:因为是个简单的bean不涉及合并bean定义
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// ... 后续步骤
}
作用 :获取合并后的 Bean 定义(RootBeanDefinition)。
处理过程:
- 对于
ServiceA,由于没有父级 Bean 定义,所以不需要合并父级的属性 - 直接封装成
RootBeanDefinition,设置默认作用域为singleton - 缓存合并后的 Bean 定义,供后续使用
步骤 8:检查 depends-on 依赖
源码位置 :AbstractBeanFactory.doGetBean()
java
// AbstractBeanFactory.java
protected <T> T doGetBean(...) {
// ... 前面的步骤
// 步骤8:因为没有配置dependsOn所以相关逻辑依旧不走
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
// 处理依赖关系(本次不关注)
}
// ... 后续步骤
}
说明 :由于 ServiceA 没有配置 depends-on 属性,所以 dependsOn 为 null,这段代码跳过。
步骤 9:进入单例创建逻辑
源码位置 :AbstractBeanFactory.doGetBean()
java
// AbstractBeanFactory.java
protected <T> T doGetBean(...) {
// ... 前面的步骤
// 步骤9:因为是单例所以走进单例创建bean的分支中
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
return createBean(beanName, mbd, args);
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
// else if (mbd.isPrototype()) { ... } // 原型Bean处理(本次不关注)
// else { ... } // 其他作用域处理(本次不关注)
}
作用 :由于 ServiceA 是单例作用域,进入单例 Bean 的创建逻辑。
关键点:
- 调用
getSingleton(String beanName, ObjectFactory<?> singletonFactory)方法 - 传入一个
ObjectFactory,用于创建 Bean 实例(延迟执行) - 这个方法内部会处理循环依赖的逻辑,通过三级缓存机制来解决
与第一篇的区别:
- 第一篇:简单的
UserService,没有循环依赖,直接创建完成 - 第三篇:
ServiceA和ServiceB存在循环依赖,需要在创建过程中处理循环依赖
总结 :通过以上 9 个步骤,doGetBean() 方法完成了 Bean 获取的前期准备工作。接下来将进入 getSingleton(beanName, singletonFactory) 方法,这里会涉及循环依赖的核心处理逻辑。
2. 自动注入的 Bean 在哪个环节初始化?
这是一个非常关键的问题!在循环依赖的场景中,当 ServiceA 创建时,需要注入 ServiceB,那么 ServiceB 是在哪个环节被初始化的呢?
答案 :自动注入的 Bean 是在 populateBean() 方法 中初始化的,具体通过 BeanDefinitionValueResolver.resolveReference() 方法调用 getBean() 触发依赖 Bean 的创建。
2.1 关键环节:populateBean 方法
让我们追踪一下完整的流程:
步骤 10-18:进入 createBean 和 doCreateBean 方法
源码位置 :AbstractAutowireCapableBeanFactory.createBean() → doCreateBean()
java
// AbstractAutowireCapableBeanFactory.java
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// ... 前面的步骤(解析Class、准备方法覆盖等)
// 进入doCreateBean方法
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
return beanInstance;
}
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// 步骤10-18:创建Bean实例、提前暴露、填充属性等
// 1. createBeanInstance() - 创建ServiceA实例(调用无参构造方法)
// 2. 提前暴露Bean到三级缓存
// 3. populateBean() - 填充属性,这里会触发ServiceB的初始化!
// 4. initializeBean() - 初始化Bean
}
关键点 :在 doCreateBean() 方法中,会依次执行:
- 创建实例 :
createBeanInstance()- 调用ServiceA的无参构造方法 - 提前暴露 :将
ServiceA的工厂对象放入三级缓存 - 填充属性 :
populateBean()- 这里会触发ServiceB的初始化! - 初始化 :
initializeBean()- 调用初始化方法
步骤 19:populateBean 方法 - 自动注入的关键环节
源码位置 :AbstractAutowireCapableBeanFactory.populateBean()
java
// AbstractAutowireCapableBeanFactory.java
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
// 获取Bean定义中的属性值
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
// 处理自动注入(本次不关注)
// if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || ...) { ... }
// 应用InstantiationAwareBeanPostProcessor(本次不关注)
// ...
// 应用属性值
if (pvs != null) {
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
作用:填充 Bean 的属性值,包括依赖注入。
关键方法 :applyPropertyValues() - 这里会解析属性值,包括 Bean 引用。
步骤 20:applyPropertyValues 方法 - 解析属性值
源码位置 :AbstractAutowireCapableBeanFactory.applyPropertyValues()
java
// AbstractAutowireCapableBeanFactory.java
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
// 创建值解析器
BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, bw);
// 遍历所有属性值
List<PropertyValue> deepCopy = new ArrayList<>(pvs.getPropertyValues().length);
for (PropertyValue pv : pvs.getPropertyValues()) {
String propertyName = pv.getName(); // "serviceB"
Object originalValue = pv.getValue(); // RuntimeBeanReference("serviceB")
// 解析属性值
Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
// 设置属性值
bw.setPropertyValue(new PropertyValue(pv.getName(), resolvedValue));
}
}
作用 :解析属性值,将 RuntimeBeanReference 转换为实际的 Bean 实例。
步骤 21:resolveValueIfNecessary 方法 - 解析 Bean 引用
源码位置 :BeanDefinitionValueResolver.resolveValueIfNecessary()
java
// BeanDefinitionValueResolver.java
public Object resolveValueIfNecessary(Object argName, Object value) {
// 如果是RuntimeBeanReference(Bean引用),需要获取Bean实例
if (value instanceof RuntimeBeanReference) {
RuntimeBeanReference ref = (RuntimeBeanReference) value;
return resolveReference(argName, ref);
}
// ... 其他类型的处理
}
private Object resolveReference(Object argName, RuntimeBeanReference ref) {
String refName = ref.getBeanName(); // "serviceB"
// 关键:这里会调用getBean()方法获取Bean实例!
Object bean = this.beanFactory.getBean(refName);
return bean;
}
关键点 :当解析到 RuntimeBeanReference("serviceB") 时,会调用 this.beanFactory.getBean("serviceB") 来获取 ServiceB 实例!
步骤 22:触发 ServiceB 的初始化
源码位置 :AbstractBeanFactory.getBean() → doGetBean()
java
// AbstractBeanFactory.java
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
protected <T> T doGetBean(String name, ...) {
// 这里会进入ServiceB的创建流程!
// 1. 解析Bean名称:"serviceB"
// 2. 从缓存获取:null(ServiceB还未创建)
// 3. 标记ServiceB正在创建
// 4. 进入createBean("serviceB", ...)流程
// 5. 在populateBean时,发现ServiceB依赖ServiceA
// 6. 从三级缓存中获取ServiceA的早期引用
// 7. 完成ServiceB的创建
}
关键流程:
-
ServiceA 创建流程:
- 创建
ServiceA实例 - 提前暴露到三级缓存
- 填充属性时发现需要
ServiceB - 调用
getBean("serviceB")
- 创建
-
ServiceB 创建流程(被触发):
- 创建
ServiceB实例 - 提前暴露到三级缓存
- 填充属性时发现需要
ServiceA - 从三级缓存中获取
ServiceA的早期引用(解决循环依赖!) - 完成
ServiceB的创建
- 创建
-
ServiceA 完成创建:
- 将
ServiceB注入到ServiceA - 完成
ServiceA的创建
- 将
2.2 完整的调用链
factory.getBean("serviceA")
↓
AbstractBeanFactory.doGetBean("serviceA")
↓
DefaultSingletonBeanRegistry.getSingleton("serviceA", singletonFactory)
↓
AbstractAutowireCapableBeanFactory.createBean("serviceA", ...)
↓
AbstractAutowireCapableBeanFactory.doCreateBean("serviceA", ...)
↓
1. createBeanInstance() - 创建ServiceA实例
↓
2. 提前暴露到三级缓存
↓
3. populateBean() - 填充属性
↓
applyPropertyValues() - 应用属性值
↓
BeanDefinitionValueResolver.resolveValueIfNecessary()
↓
BeanDefinitionValueResolver.resolveReference()
↓
beanFactory.getBean("serviceB") ← 触发ServiceB的初始化!
↓
AbstractBeanFactory.doGetBean("serviceB")
↓
... ServiceB的创建流程 ...
↓
在populateBean时,从三级缓存获取ServiceA的早期引用
↓
4. initializeBean() - 初始化ServiceA
2.3 关键发现
自动注入的 Bean 初始化时机:
- 位置 :
populateBean()方法中 - 具体方法 :
BeanDefinitionValueResolver.resolveReference() - 触发方式 :调用
beanFactory.getBean(refName)获取依赖的 Bean - 时机:在 Bean 实例创建之后,属性填充阶段
循环依赖的解决:
ServiceA创建时,提前暴露到三级缓存ServiceB创建时,需要ServiceA,从三级缓存中获取早期引用- 这样就能解决循环依赖问题
3. ServiceA 的完整创建流程(步骤 10-21)
回到步骤 9,我们进入了 getSingleton(beanName, singletonFactory) 方法。让我们继续分析 ServiceA 的创建流程,重点关注在填充属性时如何触发 ServiceB 的创建:
步骤 10:检查当前是否在销毁单例
源码位置 :DefaultSingletonBeanRegistry.getSingleton(String, ObjectFactory)
java
// DefaultSingletonBeanRegistry.java
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
synchronized (this.singletonObjects) {
// 再次从一级缓存中获取
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
// 步骤10:检查当前是否在销毁单例,否
if (this.singletonsCurrentlyInDestruction.contains(beanName)) {
throw new BeanCreationNotAllowedException(beanName,
"Singleton bean creation not allowed while singletons of this factory are in destruction");
}
// ... 后续步骤
}
}
}
说明 :检查该 Bean 是否在 singletonsCurrentlyInDestruction 集合中,如果存在则抛出异常。对于 ServiceA,不在销毁集合中,继续创建流程。
步骤 11:将 beanName 放入正在创建的单例缓存中
源码位置 :DefaultSingletonBeanRegistry.getSingleton(String, ObjectFactory)
java
// DefaultSingletonBeanRegistry.java
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
synchronized (this.singletonObjects) {
// ... 前面的步骤
// 步骤11:依旧是将beanName放入正在创建的单例缓存中
beforeSingletonCreation(beanName);
// ... 后续步骤
}
}
作用 :将 "serviceA" 放入 singletonsCurrentlyInCreation 集合,标记该 Bean 正在创建中。
关键点 :这个标记在循环依赖处理中非常重要!当 ServiceB 需要 ServiceA 时,会发现 ServiceA 正在创建中,从而从三级缓存中获取早期引用。
步骤 12:调用 createBean 方法
源码位置 :DefaultSingletonBeanRegistry.getSingleton(String, ObjectFactory)
java
// DefaultSingletonBeanRegistry.java
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
synchronized (this.singletonObjects) {
// ... 前面的步骤
// 步骤12:依旧是调用AbstractAutowireCapableBeanFactory中的createBean方法
singletonObject = singletonFactory.getObject();
// ... 后续步骤
}
}
作用 :调用传入的 ObjectFactory,执行 createBean(beanName, mbd, args) 方法。
步骤 13:根据 Bean 定义得到全限定类名
源码位置 :AbstractAutowireCapableBeanFactory.createBean()
java
// AbstractAutowireCapableBeanFactory.java
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
RootBeanDefinition mbdToUse = mbd;
// 步骤13:依旧是根据bean定义得到全限定类名
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// ... 后续步骤
}
作用:解析 Bean 的 Class 类型,从 Bean 定义中的全限定类名加载 Class 对象。
步骤 14:准备方法覆盖
源码位置 :AbstractAutowireCapableBeanFactory.createBean()
java
// AbstractAutowireCapableBeanFactory.java
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// ... 前面的步骤
// 步骤14:依旧是没有methodOverrides
// mbdToUse.prepareMethodOverrides();
// ... 后续步骤
}
说明 :由于 ServiceA 没有配置方法覆盖(lookup-method 和 replaced-method),所以跳过。
步骤 15:实例化前的后置处理
源码位置 :AbstractAutowireCapableBeanFactory.createBean()
java
// AbstractAutowireCapableBeanFactory.java
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// ... 前面的步骤
// 步骤15:依旧是用不到resolveBeforeInstantiation
// Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
// if (bean != null) { return bean; }
// ... 后续步骤
}
说明 :对于 ServiceA,没有配置 InstantiationAwareBeanPostProcessor,所以跳过。
步骤 16:进入 doCreateBean 方法
源码位置 :AbstractAutowireCapableBeanFactory.createBean()
java
// AbstractAutowireCapableBeanFactory.java
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// ... 前面的步骤
// 步骤16:依旧是doCreateBean(beanName, mbdToUse, args);
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
return beanInstance;
}
作用 :进入 doCreateBean() 方法,执行实际的 Bean 创建逻辑。
步骤 17:创建 Bean 实例
源码位置 :AbstractAutowireCapableBeanFactory.doCreateBean()
java
// AbstractAutowireCapableBeanFactory.java
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// 步骤17:依旧是通过this.createBeanInstance(beanName, mbd, args);
// 得到一个被BeanWrapperImpl封装的只有默认参数的bean对象
BeanWrapper instanceWrapper = createBeanInstance(beanName, mbd, args);
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
// ... 后续步骤
}
作用:根据 Bean 定义创建 Bean 实例。
处理过程:
- 调用
ServiceA的无参构造方法,创建ServiceA实例 - 封装在
BeanWrapperImpl中返回 - 此时
ServiceA的serviceB属性还是null
步骤 18:提前暴露 Bean 到三级缓存
源码位置 :AbstractAutowireCapableBeanFactory.doCreateBean()
java
// AbstractAutowireCapableBeanFactory.java
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// ... 前面的步骤
// 步骤18:依旧是要尽早暴露的bean,依旧是将ObjectFactory放入三级缓存中,
// 将beanName放入注册的单例缓存中
boolean earlySingletonExposure = (mbd.isSingleton() &&
this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// ... 后续步骤
}
作用:如果允许提前暴露,将 Bean 的工厂对象放入三级缓存,用于解决循环依赖。
addSingletonFactory 方法实现:
java
// DefaultSingletonBeanRegistry.java
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
synchronized (this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
// 将ObjectFactory放入三级缓存singletonFactories中
this.singletonFactories.put(beanName, singletonFactory);
// 从二级缓存earlySingletonObjects中移除该beanName(如果存在)
this.earlySingletonObjects.remove(beanName);
// 在registeredSingletons中添加该beanName
this.registeredSingletons.add(beanName);
}
}
}
关键点:
- 将
ServiceA的工厂对象放入三级缓存singletonFactories中 - 这样当
ServiceB需要ServiceA时,可以从三级缓存中获取早期引用 - 这是解决循环依赖的核心机制!
步骤 19:进入 populateBean 方法
源码位置 :AbstractAutowireCapableBeanFactory.doCreateBean()
java
// AbstractAutowireCapableBeanFactory.java
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// ... 前面的步骤
// 步骤19:依旧是进入populateBean,但这里面可能存在不一样的逻辑,
// 至少获取到了依赖的ServiceB也是Bean
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
// ... 异常处理
}
// ... 后续步骤
}
作用:填充 Bean 的属性值,包括依赖注入。
populateBean 方法实现:
java
// AbstractAutowireCapableBeanFactory.java
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
// 获取Bean定义中的属性值
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
// 处理自动注入(本次不关注)
// if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || ...) { ... }
// 应用InstantiationAwareBeanPostProcessor(本次不关注)
// ...
// 应用属性值
if (pvs != null) {
// 关键:这里会触发依赖Bean的创建!
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
关键点 :pvs 是 MutablePropertyValues 类型,包含了 ServiceA 的所有属性值,包括 serviceB 的引用。
步骤 20:深入 applyPropertyValues 方法
源码位置 :AbstractAutowireCapableBeanFactory.applyPropertyValues()
java
// AbstractAutowireCapableBeanFactory.java
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
// 步骤20:在mpvs.getPropertyValueList()获得所有属性
// 中需要深入探索:是否存在回调创建依赖的Bean
if (pvs.isEmpty()) {
return;
}
// 创建值解析器
BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, bw);
// 获取类型转换器
// this.getCustomTypeConverter()是null,使用默认的bw进行解析
TypeConverter converter = (this.getCustomTypeConverter() != null ?
this.getCustomTypeConverter() : bw);
// 创建属性值的深拷贝列表
List<PropertyValue> deepCopy = new ArrayList<>(pvs.getPropertyValues().length);
boolean resolveNecessary = false;
// 遍历所有属性值
for (PropertyValue pv : pvs.getPropertyValues()) {
String propertyName = pv.getName(); // "serviceB"
Object originalValue = pv.getValue(); // RuntimeBeanReference("serviceB")
// 解析属性值 - 这里会触发依赖Bean的创建!
Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
// 添加到深拷贝列表
deepCopy.add(new PropertyValue(pv.getName(), resolvedValue));
}
// 设置属性值到BeanWrapper
bw.setPropertyValues(new MutablePropertyValues(deepCopy));
}
关键点:
-
PropertyValues 不是简单的实体类:
PropertyValues是一个接口,MutablePropertyValues是其实现- 它包含了 Bean 的所有属性值,包括基本类型和 Bean 引用
- 每个
PropertyValue包含属性名和属性值(可能是RuntimeBeanReference)
-
遍历属性值:
- 通过
pvs.getPropertyValues()获取所有属性值 - 对于
ServiceA,会遍历到serviceB属性
- 通过
-
解析属性值:
- 调用
valueResolver.resolveValueIfNecessary(pv, originalValue) - 当
originalValue是RuntimeBeanReference("serviceB")时,会触发getBean("serviceB")的调用!
- 调用
-
类型转换器:
this.getCustomTypeConverter()是null,使用默认的bw(BeanWrapperImpl)进行解析BeanWrapperImpl实现了TypeConverter接口,用于类型转换
PropertyValues 的结构:
java
// MutablePropertyValues.java
public class MutablePropertyValues implements PropertyValues {
private final List<PropertyValue> propertyValueList;
public PropertyValue[] getPropertyValues() {
return this.propertyValueList.toArray(new PropertyValue[0]);
}
}
// PropertyValue.java
public class PropertyValue {
private final String name; // "serviceB"
private final Object value; // RuntimeBeanReference("serviceB")
}
关键发现 :在 applyPropertyValues() 方法中,遍历属性值时,会调用 resolveValueIfNecessary() 来解析每个属性值。当属性值是 RuntimeBeanReference 时,会触发依赖 Bean 的创建!
步骤 21:BeanDefinitionValueResolver 解析属性值
源码位置 :AbstractAutowireCapableBeanFactory.applyPropertyValues()
java
// AbstractAutowireCapableBeanFactory.java
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
// 步骤21:用当前beanFactory、beanName、bean定义、beanWrapper组成了BeanDefinitionValueResolver对象
BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, bw);
// 遍历bean的每个属性:这里重点看ServiceB
for (PropertyValue pv : pvs.getPropertyValues()) {
String propertyName = pv.getName(); // "serviceB"
Object originalValue = pv.getValue(); // RuntimeBeanReference("serviceB")
// 解析属性值
Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
// ... 后续处理
}
}
BeanDefinitionValueResolver 的构造:
java
// BeanDefinitionValueResolver.java
public BeanDefinitionValueResolver(BeanFactory beanFactory, String beanName,
BeanDefinition beanDefinition, TypeConverter typeConverter) {
this.beanFactory = beanFactory; // 当前BeanFactory
this.beanName = beanName; // "serviceA"
this.beanDefinition = beanDefinition; // ServiceA的Bean定义
this.typeConverter = typeConverter; // BeanWrapperImpl
}
作用 :创建值解析器,用于将属性值描述(如 RuntimeBeanReference)解析为实际的 Bean 实例。
resolveValueIfNecessary 方法实现:
java
// BeanDefinitionValueResolver.java
public Object resolveValueIfNecessary(Object argName, Object value) {
// 步骤21:在resolveValueIfNecessary方法中serviceB是个RuntimeBeanReference
// 这里其实就对上了Bean定义注册的流程,那个时候将ref标签注册为RuntimeBeanReference
if (value instanceof RuntimeBeanReference) {
RuntimeBeanReference ref = (RuntimeBeanReference) value;
return resolveReference(argName, ref);
}
// ... 其他类型的处理(TypedStringValue、ManagedList等)
}
关键点:
- 在 XML 配置解析阶段,
<property name="serviceB" ref="serviceB"/>中的ref标签被解析为RuntimeBeanReference("serviceB") - 这个
RuntimeBeanReference对象存储在BeanDefinition的PropertyValues中 - 现在在属性填充阶段,需要将这个引用解析为实际的 Bean 实例
resolveReference 方法实现:
java
// BeanDefinitionValueResolver.java
private Object resolveReference(Object argName, RuntimeBeanReference ref) {
String refName = ref.getBeanName(); // "serviceB"
// 步骤21:通过this.doEvaluate(ref.getBeanName())解析出bean名称,当然这里也可能是别名
refName = String.valueOf(doEvaluate(refName));
// 步骤21:解析来用这个名字回调this.beanFactory.getBean(resolvedName)
Object bean = this.beanFactory.getBean(refName);
// 注册依赖关系
this.beanFactory.registerDependentBean(refName, this.beanName);
return bean;
}
doEvaluate 方法:
java
// BeanDefinitionValueResolver.java
protected Object doEvaluate(@Nullable String value) {
// 如果value是表达式(如${...}或#{...}),需要解析表达式
// 对于简单的bean名称或别名,直接返回
if (!StringUtils.hasText(value)) {
return value;
}
// ... 表达式解析逻辑(本次不关注)
return value;
}
处理过程:
-
获取 Bean 名称:
- 从
RuntimeBeanReference中获取beanName:"serviceB" - 调用
doEvaluate()方法解析(可能是表达式,也可能是别名)
- 从
-
解析别名:
- 如果
"serviceB"是别名,doEvaluate()会通过别名映射表转换为实际的 Bean 名称 - 对于我们的示例,
"serviceB"就是实际的 Bean 名称,不需要转换
- 如果
-
回调 getBean:
- 调用
this.beanFactory.getBean(refName)获取ServiceB实例 - 这里会触发
ServiceB的创建流程!
- 调用
-
注册依赖关系:
- 调用
registerDependentBean(refName, this.beanName)注册依赖关系 - 记录
"serviceA"依赖于"serviceB"
- 调用
完整的调用链:
applyPropertyValues("serviceA", mbd, bw, pvs)
↓
遍历PropertyValue: name="serviceB", value=RuntimeBeanReference("serviceB")
↓
valueResolver.resolveValueIfNecessary(pv, RuntimeBeanReference("serviceB"))
↓
resolveReference(argName, RuntimeBeanReference("serviceB"))
↓
ref.getBeanName() → "serviceB"
↓
doEvaluate("serviceB") → "serviceB"(可能是别名转换)
↓
this.beanFactory.getBean("serviceB") ← 触发ServiceB的创建!
↓
AbstractBeanFactory.doGetBean("serviceB")
↓
... ServiceB的创建流程 ...
↓
在populateBean时,发现ServiceB依赖ServiceA
↓
从三级缓存获取ServiceA的早期引用
↓
完成ServiceB的创建,返回ServiceB实例
↓
将ServiceB实例注入到ServiceA的serviceB属性中
与 Bean 定义注册流程的对应关系:
在 XML 配置解析阶段(BeanDefinitionParserDelegate.parsePropertyElement()):
java
// BeanDefinitionParserDelegate.java
public void parsePropertyElement(Element ele, BeanDefinition bd) {
String propertyName = ele.getAttribute(NAME_ATTRIBUTE); // "serviceB"
String ref = ele.getAttribute(REF_ATTRIBUTE); // "serviceB"
if (StringUtils.hasLength(ref)) {
// 将ref标签注册为RuntimeBeanReference
RuntimeBeanReference refObj = new RuntimeBeanReference(ref);
bd.getPropertyValues().addPropertyValue(propertyName, refObj);
}
}
关键发现:
-
Bean 定义注册阶段:
- XML 中的
<property name="serviceB" ref="serviceB"/>被解析为RuntimeBeanReference("serviceB") - 存储在
BeanDefinition的PropertyValues中
- XML 中的
-
Bean 创建阶段:
- 在
populateBean()时,遍历PropertyValues - 发现
RuntimeBeanReference,调用resolveReference()解析 - 通过
getBean("serviceB")触发依赖 Bean 的创建
- 在
-
循环依赖的解决:
ServiceA创建时,提前暴露到三级缓存ServiceB创建时,需要ServiceA,从三级缓存中获取早期引用- 完成
ServiceB的创建后,返回给ServiceA使用
4. ServiceB 创建过程中的循环依赖处理
至此,关键的一环找到了!在 resolveReference() 方法中确实有回调 getBean("serviceB")。那么接下来更重要的就是:当 ServiceB 这个 Bean 创建过程中,解析到依赖 ServiceA 时会发生什么?
4.1 ServiceB 的创建流程(前半部分)
当 ServiceA 在 populateBean() 时调用 getBean("serviceB"),会触发 ServiceB 的创建流程:
ServiceB 的 doGetBean 流程(步骤 1-9)
源码位置 :AbstractBeanFactory.doGetBean("serviceB")
java
// AbstractBeanFactory.java
protected <T> T doGetBean(String name, ...) {
// 步骤1:解析Bean名称
final String beanName = transformedBeanName(name); // "serviceB"
// 步骤2:获取缓存中的单例对象
Object sharedInstance = getSingleton(beanName);
// 此时ServiceB还未创建,返回null
// 步骤3:检查循环依赖(单例作用域,跳过)
// 步骤4:检查父级BeanFactory(没有,跳过)
// 步骤5:标记Bean正在被创建
if (!typeCheckOnly) {
markBeanAsCreated(beanName); // 将"serviceB"加入alreadyCreated
}
// 步骤6:ApplicationStartup处理(跳过)
// 步骤7:获取合并后的Bean定义
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// 步骤8:检查是否为抽象Bean(否)
// 步骤9:进入单例创建逻辑
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
return createBean(beanName, mbd, args);
});
}
}
关键点 :ServiceB 的创建流程与 ServiceA 类似,但接下来会有不同的处理。
ServiceB 的 getSingleton 流程(步骤 10-18)
源码位置 :DefaultSingletonBeanRegistry.getSingleton("serviceB", singletonFactory)
java
// DefaultSingletonBeanRegistry.java
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
synchronized (this.singletonObjects) {
// 步骤10:检查是否在销毁(否)
// 步骤11:将beanName放入正在创建的单例缓存中
beforeSingletonCreation(beanName); // 将"serviceB"加入singletonsCurrentlyInCreation
// 步骤12:调用createBean方法
singletonObject = singletonFactory.getObject();
// ... 后续步骤
}
}
关键点 :此时 singletonsCurrentlyInCreation 中包含:
"serviceA"(正在创建)"serviceB"(刚刚加入,正在创建)
ServiceB 的 createBean 和 doCreateBean 流程(步骤 13-18)
源码位置 :AbstractAutowireCapableBeanFactory.createBean() → doCreateBean()
java
// AbstractAutowireCapableBeanFactory.java
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// 步骤13-16:解析Class、准备方法覆盖、实例化前处理、进入doCreateBean
// 步骤17:创建Bean实例
BeanWrapper instanceWrapper = createBeanInstance(beanName, mbd, args);
// 调用ServiceB的无参构造方法,创建ServiceB实例
// 此时ServiceB的serviceA属性还是null
// 步骤18:提前暴露Bean到三级缓存
boolean earlySingletonExposure = (mbd.isSingleton() &&
this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
// 将ServiceB的工厂对象放入三级缓存
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// ... 后续步骤
}
关键点:
ServiceB实例已创建(但serviceA属性为null)ServiceB的工厂对象已放入三级缓存singletonFactories中
4.2 ServiceB 填充属性时发现依赖 ServiceA
步骤 19:ServiceB 进入 populateBean
源码位置 :AbstractAutowireCapableBeanFactory.doCreateBean()
java
// AbstractAutowireCapableBeanFactory.java
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// ... 前面的步骤
// 步骤19:进入populateBean,填充ServiceB的属性
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
// 这里会发现ServiceB依赖ServiceA!
// ... 后续步骤
}
}
步骤 20-21:ServiceB 解析属性值
源码位置 :AbstractAutowireCapableBeanFactory.applyPropertyValues()
java
// AbstractAutowireCapableBeanFactory.java
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, bw);
// 遍历ServiceB的属性值
for (PropertyValue pv : pvs.getPropertyValues()) {
String propertyName = pv.getName(); // "serviceA"
Object originalValue = pv.getValue(); // RuntimeBeanReference("serviceA")
// 解析属性值
Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
// 这里会触发getBean("serviceA")!
}
}
步骤 22:ServiceB 调用 getBean("serviceA")
源码位置 :BeanDefinitionValueResolver.resolveReference()
java
// BeanDefinitionValueResolver.java
private Object resolveReference(Object argName, RuntimeBeanReference ref) {
String refName = ref.getBeanName(); // "serviceA"
refName = String.valueOf(doEvaluate(refName)); // "serviceA"
// 关键:ServiceB需要ServiceA,调用getBean("serviceA")
Object bean = this.beanFactory.getBean(refName);
return bean;
}
关键点 :ServiceB 在填充属性时,发现需要 ServiceA,调用 getBean("serviceA")。
4.3 关键环节:从三级缓存获取 ServiceA 的早期引用
步骤 23:ServiceA 的 doGetBean(第二次调用)
源码位置 :AbstractBeanFactory.doGetBean("serviceA")
java
// AbstractBeanFactory.java
protected <T> T doGetBean(String name, ...) {
// 步骤1:解析Bean名称
final String beanName = transformedBeanName(name); // "serviceA"
// 步骤2:获取缓存中的单例对象 - 关键!
Object sharedInstance = getSingleton(beanName);
// 这里会从三级缓存中获取ServiceA的早期引用!
// ... 后续步骤
}
关键点 :这是 ServiceA 的第二次 getBean() 调用(第一次是用户调用,第二次是 ServiceB 依赖注入时调用)。
步骤 24:getSingleton 方法中的三级缓存查找
源码位置 :DefaultSingletonBeanRegistry.getSingleton(String)
java
// DefaultSingletonBeanRegistry.java
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 第一级缓存:完全初始化好的单例Bean
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject != null) {
return singletonObject; // ServiceA还未完成,返回null
}
// 关键:如果允许提前引用,且Bean正在创建中
if (isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
// 第二级缓存:提前暴露的单例Bean
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
// 第三级缓存:单例Bean的工厂对象
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// 关键:从三级缓存中获取ServiceA的早期引用!
singletonObject = singletonFactory.getObject();
// 将早期引用放入二级缓存
this.earlySingletonObjects.put(beanName, singletonObject);
// 从三级缓存中移除
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
处理过程:
-
检查一级缓存:
- 从
singletonObjects中查找"serviceA",返回null(ServiceA还未完成创建)
- 从
-
检查是否正在创建:
- 调用
isSingletonCurrentlyInCreation("serviceA"),返回true(ServiceA在singletonsCurrentlyInCreation中)
- 调用
-
检查二级缓存:
- 从
earlySingletonObjects中查找"serviceA",返回null(还未放入二级缓存)
- 从
-
从三级缓存获取:
- 从
singletonFactories中获取ServiceA的工厂对象 - 调用
singletonFactory.getObject()获取ServiceA的早期引用 - 这是解决循环依赖的关键!
- 从
-
升级到二级缓存:
- 将早期引用放入二级缓存
earlySingletonObjects - 从三级缓存
singletonFactories中移除
- 将早期引用放入二级缓存
getEarlyBeanReference 方法:
java
// AbstractAutowireCapableBeanFactory.java
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
// 应用后置处理器(可能返回代理对象)
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);
}
}
return exposedObject;
}
作用:获取 Bean 的早期引用,可能经过后置处理器处理(如 AOP 代理)。
4.4 完整的循环依赖解决流程
1. 用户调用:factory.getBean("serviceA")
↓
2. ServiceA开始创建
- 创建ServiceA实例(serviceB属性为null)
- 提前暴露到三级缓存:singletonFactories.put("serviceA", factory)
↓
3. ServiceA填充属性
- 发现需要ServiceB
- 调用getBean("serviceB")
↓
4. ServiceB开始创建
- 创建ServiceB实例(serviceA属性为null)
- 提前暴露到三级缓存:singletonFactories.put("serviceB", factory)
↓
5. ServiceB填充属性
- 发现需要ServiceA
- 调用getBean("serviceA")
↓
6. ServiceA的第二次getBean调用
- 从一级缓存查找:null(还未完成)
- 检查是否正在创建:true(在singletonsCurrentlyInCreation中)
- 从三级缓存获取:singletonFactories.get("serviceA")
- 调用factory.getObject()获取早期引用
- 放入二级缓存:earlySingletonObjects.put("serviceA", earlyRef)
- 从三级缓存移除:singletonFactories.remove("serviceA")
↓
7. 返回ServiceA的早期引用给ServiceB
- ServiceB的serviceA属性被注入
- 完成ServiceB的创建
- 放入一级缓存:singletonObjects.put("serviceB", serviceB)
↓
8. 返回ServiceB给ServiceA
- ServiceA的serviceB属性被注入
- 完成ServiceA的创建
- 放入一级缓存:singletonObjects.put("serviceA", serviceA)
- 从二级缓存移除:earlySingletonObjects.remove("serviceA")
4.5 三级缓存的作用
一级缓存 singletonObjects:
- 存储完全初始化好的单例 Bean
- 最终的目标缓存
二级缓存 earlySingletonObjects:
- 存储提前暴露的单例 Bean(早期引用)
- 用于避免重复从三级缓存获取
三级缓存 singletonFactories:
- 存储单例 Bean 的工厂对象
- 用于获取 Bean 的早期引用(可能经过后置处理器处理)
为什么需要三级缓存?
- 一级缓存:存储最终完成的 Bean
- 二级缓存:避免重复调用工厂对象(性能优化)
- 三级缓存:存储工厂对象,可以获取经过后置处理器处理的早期引用(如 AOP 代理)
关键发现:
- 循环依赖的解决:通过三级缓存机制,在 Bean 还未完全初始化时,提前暴露早期引用
- 时机 :在
populateBean()阶段,当发现依赖的 Bean 正在创建时,从三级缓存获取早期引用 - 条件 :必须是单例 Bean,且允许循环依赖(
allowCircularReferences = true)
4.6 ServiceB 的 populateBean 详细流程
继续来到 ServiceB 这个 Bean 到 populateBean 方法的逻辑:
步骤 25:ServiceB 进入 populateBean
源码位置 :AbstractAutowireCapableBeanFactory.doCreateBean()
java
// AbstractAutowireCapableBeanFactory.java
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// ... 前面的步骤(创建实例、提前暴露)
// 步骤25:进入populateBean,填充ServiceB的属性
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
// 带着PropertyValues调用applyPropertyValues
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
// ... 异常处理
}
// ... 后续步骤
}
步骤 26:ServiceB 调用 applyPropertyValues
源码位置 :AbstractAutowireCapableBeanFactory.populateBean()
java
// AbstractAutowireCapableBeanFactory.java
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
// 获取Bean定义中的属性值
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
// 步骤26:带着PropertyValues调用applyPropertyValues
if (pvs != null) {
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
PropertyValues 内容:
pvs包含ServiceB的所有属性值- 其中有一个
PropertyValue:name="serviceA",value=RuntimeBeanReference("serviceA")
步骤 27:ServiceB 遍历属性值
源码位置 :AbstractAutowireCapableBeanFactory.applyPropertyValues()
java
// AbstractAutowireCapableBeanFactory.java
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, bw);
// 步骤27:依旧是到遍历属性的逻辑中
// 你会发现和刚刚的调用如出一辙
for (PropertyValue pv : pvs.getPropertyValues()) {
String propertyName = pv.getName(); // "serviceA"
Object originalValue = pv.getValue(); // RuntimeBeanReference("serviceA")
// 解析属性值
Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
// 这里会触发getBean("serviceA")!
}
}
关键点:
- 遍历逻辑与
ServiceA填充属性时完全一样 - 发现
RuntimeBeanReference("serviceA"),需要解析为实际的 Bean 实例
步骤 28:ServiceB 调用 getBean("serviceA")
源码位置 :BeanDefinitionValueResolver.resolveReference()
java
// BeanDefinitionValueResolver.java
private Object resolveReference(Object argName, RuntimeBeanReference ref) {
String refName = ref.getBeanName(); // "serviceA"
refName = String.valueOf(doEvaluate(refName)); // "serviceA"
// 步骤28:最终又走进了this.beanFactory.getBean(resolvedName)方法中去获取serviceA个bean
// 但这次getBean的方法走了不同的逻辑!
Object bean = this.beanFactory.getBean(refName);
return bean;
}
关键点 :这次调用 getBean("serviceA") 会走不同的逻辑,因为 ServiceA 已经在创建过程中了!
步骤 29:ServiceA 的第二次 doGetBean(关键!)
源码位置 :AbstractBeanFactory.doGetBean("serviceA")
java
// AbstractBeanFactory.java
protected <T> T doGetBean(String name, ...) {
// 步骤1:解析Bean名称
final String beanName = transformedBeanName(name); // "serviceA"
// 步骤2:获取缓存中的单例对象 - 关键!
Object sharedInstance = getSingleton(beanName);
// 这次会从三级缓存中获取ServiceA的早期引用!
if (sharedInstance != null && args == null) {
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
return bean; // 直接返回,不再进入创建流程
}
// ... 如果缓存中没有,才会进入创建流程(本次不会走这里)
}
关键点 :这是 ServiceA 的第二次 getBean() 调用,但这次会从缓存中获取到早期引用,不会再次进入创建流程。
步骤 30:从三级缓存获取早期引用(核心逻辑)
源码位置 :DefaultSingletonBeanRegistry.getSingleton(String)
java
// DefaultSingletonBeanRegistry.java
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 第一级缓存:完全初始化好的单例Bean
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject != null) {
return singletonObject; // ServiceA还未完成,返回null
}
// 关键:如果允许提前引用,且Bean正在创建中
if (isSingletonCurrentlyInCreation(beanName)) {
// 步骤30:就在this.getSingleton(beanName)中他获取到了三级缓存singletonFactories中的
// ObjectFactory这个匿名内部类的对象
synchronized (this.singletonObjects) {
// 第二级缓存:提前暴露的单例Bean
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
// 第三级缓存:单例Bean的工厂对象
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// 关键:并将这可能还不完全的对象获取出来
singletonObject = singletonFactory.getObject();
// 放入二级缓存中暂时解决依赖的问题
this.earlySingletonObjects.put(beanName, singletonObject);
// 并将其从三级缓存中删除
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
处理过程详解:
-
检查一级缓存:
singletonObjects.get("serviceA")返回null(ServiceA还未完成创建)
-
检查是否正在创建:
isSingletonCurrentlyInCreation("serviceA")返回true- 因为
ServiceA在singletonsCurrentlyInCreation集合中
-
检查二级缓存:
earlySingletonObjects.get("serviceA")返回null(第一次获取,还未放入二级缓存)
-
从三级缓存获取:
-
singletonFactories.get("serviceA")返回ObjectFactory(匿名内部类对象) -
这个
ObjectFactory是在步骤 18 中放入的:javaaddSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
-
-
调用工厂对象获取早期引用:
singletonFactory.getObject()调用匿名内部类的get()方法- 执行
getEarlyBeanReference("serviceA", mbd, serviceAInstance) - 返回
ServiceA的早期引用(可能经过后置处理器处理)
-
升级到二级缓存:
earlySingletonObjects.put("serviceA", singletonObject)- 放入二级缓存singletonFactories.remove("serviceA")- 从三级缓存删除
为什么从三级缓存删除?
- 避免重复调用工厂对象(性能优化)
- 后续如果需要
ServiceA的早期引用,直接从二级缓存获取即可
步骤 31:返回 ServiceA 的早期引用给 ServiceB
源码位置 :AbstractBeanFactory.doGetBean()
java
// AbstractBeanFactory.java
protected <T> T doGetBean(...) {
Object sharedInstance = getSingleton(beanName); // 获取到ServiceA的早期引用
if (sharedInstance != null && args == null) {
// 步骤31:处理FactoryBean的情况(ServiceA不是FactoryBean,直接返回)
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
return bean; // 返回ServiceA的早期引用
}
}
关键点:
ServiceA的早期引用被返回给ServiceBServiceB的serviceA属性被注入这个早期引用- 虽然
ServiceA还未完全初始化(serviceB属性可能还是null),但对象已经创建,可以注入
步骤 32:ServiceB 完成属性填充和初始化
源码位置 :AbstractAutowireCapableBeanFactory.doCreateBean()
java
// AbstractAutowireCapableBeanFactory.java
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// ... 前面的步骤
// 步骤32:ServiceB完成属性填充
populateBean(beanName, mbd, instanceWrapper);
// ServiceB的serviceA属性已经被注入(ServiceA的早期引用)
// 步骤33:ServiceB完成初始化
exposedObject = initializeBean(beanName, exposedObject, mbd);
// 调用Aware方法、BeanPostProcessor、初始化方法等
// 步骤34:ServiceB完成创建,放入一级缓存
// 在getSingleton方法中会调用addSingleton
return exposedObject;
}
关键点:
ServiceB的serviceA属性已经注入(ServiceA的早期引用)ServiceB完成初始化后,放入一级缓存singletonObjects
步骤 35:ServiceA 完成属性填充和初始化
源码位置 :回到 ServiceA 的创建流程
java
// AbstractAutowireCapableBeanFactory.java
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// ... 前面的步骤(创建实例、提前暴露、填充属性时触发ServiceB创建)
// 步骤35:ServiceA完成属性填充
populateBean(beanName, mbd, instanceWrapper);
// ServiceA的serviceB属性已经被注入(ServiceB实例,已完成创建)
// 步骤36:ServiceA完成初始化
exposedObject = initializeBean(beanName, exposedObject, mbd);
// 步骤37:ServiceA完成创建,放入一级缓存
// 在getSingleton方法中会调用addSingleton
return exposedObject;
}
关键点:
ServiceA的serviceB属性已经注入(ServiceB实例,已完成创建)ServiceA完成初始化后,放入一级缓存singletonObjects- 从二级缓存
earlySingletonObjects中移除"serviceA"
4.7 再往后看就和之前普通的 Bean 定义一样的逻辑了
后续流程:
-
initializeBean:
- 调用
invokeAwareMethods()- 如果实现了 Aware 接口 - 调用
applyBeanPostProcessorsBeforeInitialization()- BeanPostProcessor 前置处理 - 调用
invokeInitMethods()- 初始化方法 - 调用
applyBeanPostProcessorsAfterInitialization()- BeanPostProcessor 后置处理
- 调用
-
注册单例 Bean:
- 调用
addSingleton(beanName, singletonObject) - 放入一级缓存
singletonObjects - 从二级缓存和三级缓存中删除
- 调用
-
返回 Bean 实例:
- 返回完全初始化好的 Bean 实例
与第一篇的区别:
| 对比项 | 第一篇(UserService) | 第三篇(ServiceA/ServiceB) |
|---|---|---|
| 依赖关系 | 无依赖 | 循环依赖 |
| 属性填充 | 无属性注入 | 需要注入依赖 Bean |
| 缓存使用 | 只使用一级缓存 | 使用三级缓存机制 |
| 创建流程 | 直接创建完成 | 需要处理循环依赖 |
关键发现:
-
循环依赖的解决时机:
- 在
populateBean()阶段,当发现依赖的 Bean 正在创建时 - 从三级缓存获取早期引用,而不是等待 Bean 完全创建完成
- 在
-
三级缓存的作用:
- 一级缓存:存储完全初始化好的 Bean
- 二级缓存:存储早期引用(避免重复调用工厂对象)
- 三级缓存:存储工厂对象(可以获取经过后置处理器处理的早期引用)
-
为什么需要三级缓存:
- 如果只有两级缓存,无法获取经过后置处理器处理的早期引用(如 AOP 代理)
- 三级缓存通过工厂对象延迟获取,可以应用后置处理器
5. 总结
5.1 循环依赖解决的核心机制
三级缓存机制:
-
一级缓存
singletonObjects:- 存储完全初始化好的单例 Bean
- 最终的目标缓存
-
二级缓存
earlySingletonObjects:- 存储提前暴露的单例 Bean(早期引用)
- 用于避免重复从三级缓存获取(性能优化)
-
三级缓存
singletonFactories:- 存储单例 Bean 的工厂对象(
ObjectFactory) - 用于获取 Bean 的早期引用(可能经过后置处理器处理)
- 存储单例 Bean 的工厂对象(
解决流程:
ServiceA创建 → 提前暴露到三级缓存 → 填充属性时发现需要ServiceB
↓
ServiceB创建 → 提前暴露到三级缓存 → 填充属性时发现需要ServiceA
↓
从三级缓存获取ServiceA的早期引用 → 升级到二级缓存
↓
完成ServiceB的创建 → 返回给ServiceA
↓
完成ServiceA的创建 → 放入一级缓存
5.2 关键步骤总结
ServiceA 的创建流程:
-
步骤 1-9 :
doGetBean()的前期准备- 解析 Bean 名称、检查缓存、标记正在创建等
-
步骤 10-18:进入创建流程
- 创建
ServiceA实例 - 提前暴露到三级缓存(关键!)
- 创建
-
步骤 19-21:填充属性
- 发现需要
ServiceB - 调用
getBean("serviceB")触发ServiceB的创建
- 发现需要
ServiceB 的创建流程:
-
步骤 1-18 :与
ServiceA类似的创建流程- 创建
ServiceB实例 - 提前暴露到三级缓存
- 创建
-
步骤 19-22:填充属性
- 发现需要
ServiceA - 调用
getBean("serviceA")(第二次调用)
- 发现需要
-
步骤 23-24:从三级缓存获取早期引用
- 检查一级缓存:
null(还未完成) - 检查是否正在创建:
true - 从三级缓存获取
ObjectFactory - 调用工厂对象获取早期引用
- 放入二级缓存,从三级缓存删除
- 检查一级缓存:
-
步骤 25-37:完成创建
ServiceB完成属性填充和初始化ServiceA完成属性填充和初始化- 放入一级缓存
5.3 与第一篇、第二篇的对比
| 对比项 | 第一篇(UserService) | 第二篇(别名获取) | 第三篇(循环依赖) |
|---|---|---|---|
| 场景 | 最简单的 Bean | 通过别名获取已缓存的 Bean | 单例 Bean 的循环依赖 |
| 依赖关系 | 无依赖 | 无依赖 | 循环依赖(ServiceA ↔ ServiceB) |
| 缓存使用 | 只使用一级缓存 | 只使用一级缓存 | 使用三级缓存机制 |
| 执行步骤 | 30 个步骤 | 3 个步骤 | 37+ 个步骤 |
| 关键机制 | Bean 创建流程 | 别名转换 + 缓存查找 | 三级缓存解决循环依赖 |
| 性能 | 需要创建 Bean | O(1) 缓存查找 | 需要处理循环依赖 |
5.4 关键发现
-
自动注入的 Bean 初始化时机:
- 位置 :
populateBean()方法中 - 具体方法 :
BeanDefinitionValueResolver.resolveReference() - 触发方式 :调用
beanFactory.getBean(refName)获取依赖的 Bean - 时机:在 Bean 实例创建之后,属性填充阶段
- 位置 :
-
循环依赖的解决条件:
- 必须是单例 Bean (
scope="singleton") - 必须允许循环依赖(
allowCircularReferences = true) - 必须使用属性注入(不能是构造器注入)
- 必须是单例 Bean (
-
三级缓存的设计原因:
- 一级缓存:存储最终完成的 Bean
- 二级缓存:避免重复调用工厂对象(性能优化)
- 三级缓存:存储工厂对象,可以获取经过后置处理器处理的早期引用(如 AOP 代理)
-
为什么需要三级缓存而不是两级:
- 如果只有两级缓存,无法获取经过后置处理器处理的早期引用
- 三级缓存通过工厂对象延迟获取,可以在获取时应用后置处理器
- 这对于 AOP 代理等场景非常重要
5.5 性能分析
时间复杂度:
- 循环依赖检测:O(1),通过
singletonsCurrentlyInCreation集合判断 - 三级缓存查找:O(1),
ConcurrentHashMap.get()操作 - 工厂对象调用:O(1),但可能触发后置处理器(如 AOP 代理)
空间复杂度:
- 一级缓存:O(n),n 为单例 Bean 数量
- 二级缓存:O(m),m 为正在创建且有循环依赖的 Bean 数量(通常很小)
- 三级缓存:O(m),与二级缓存相同
实际性能:
- 循环依赖会增加 Bean 创建的时间复杂度
- 但通过三级缓存机制,避免了死锁和无限递归
- 对于大多数场景,性能影响可以忽略不计
5.6 注意事项
-
构造器注入不支持循环依赖:
- 构造器注入在实例化之前就需要依赖的 Bean
- 此时 Bean 还未创建,无法提前暴露到三级缓存
- 因此构造器注入的循环依赖会抛出异常
-
原型 Bean 不支持循环依赖:
- 原型 Bean 每次获取都创建新实例
- 无法通过缓存机制解决循环依赖
- 会抛出
BeanCurrentlyInCreationException异常
-
循环依赖的限制:
- 必须是单例 Bean
- 必须使用属性注入
- 必须允许循环依赖(
allowCircularReferences = true)
5.7 核心要点回顾
-
自动注入的触发时机:
- 在
populateBean()方法中,通过BeanDefinitionValueResolver.resolveReference()触发 - 调用
getBean()获取依赖的 Bean,形成递归调用
- 在
-
循环依赖的解决机制:
- 通过三级缓存机制,在 Bean 还未完全初始化时提前暴露早期引用
- 当依赖的 Bean 正在创建时,从三级缓存获取早期引用
- 完成依赖注入后,继续完成 Bean 的初始化
-
三级缓存的设计:
- 一级缓存:存储最终完成的 Bean
- 二级缓存:存储早期引用(性能优化)
- 三级缓存:存储工厂对象(支持后置处理器处理)
-
关键方法:
addSingletonFactory():将 Bean 的工厂对象放入三级缓存getSingleton(beanName):从三级缓存获取早期引用resolveReference():解析 Bean 引用,触发依赖 Bean 的创建