【Spring源码】getBean源码实战(三)

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() 方法注入)
  • 形成了 ServiceAServiceB 的循环依赖

关键点

  • 两个 Bean 都是单例作用域 (默认 scope="singleton"
  • 使用属性注入<property> 标签),而不是构造器注入
  • Spring 通过三级缓存机制来解决单例 Bean 的循环依赖问题

1.4 执行流程概述

当我们调用 factory.getBean("serviceA") 时,Spring 会执行以下步骤:

  1. 开始创建 ServiceA

    • 创建 ServiceA 实例(调用无参构造方法)
    • ServiceA 的工厂对象放入三级缓存
  2. 填充 ServiceA 的属性

    • 发现 ServiceA 依赖 ServiceB
    • 调用 getBean("serviceB") 获取 ServiceB
  3. 开始创建 ServiceB

    • 创建 ServiceB 实例(调用无参构造方法)
    • ServiceB 的工厂对象放入三级缓存
  4. 填充 ServiceB 的属性

    • 发现 ServiceB 依赖 ServiceA
    • 从三级缓存中获取 ServiceA 的早期引用(提前暴露的对象)
  5. 完成 ServiceB 的创建

    • ServiceB 创建完成,放入一级缓存
  6. 完成 ServiceA 的创建

    • ServiceB 注入到 ServiceA
    • ServiceA 创建完成,放入一级缓存

核心机制 :Spring 使用三级缓存singletonObjectsearlySingletonObjectssingletonFactories)来解决循环依赖问题。

1.5 深入 doGetBean 方法(循环依赖处理流程)

当我们调用 factory.getBean("serviceA") 时,Spring 会进入 AbstractBeanFactory.doGetBean() 方法。由于 ServiceAServiceB 之间存在循环依赖,整个流程会涉及三级缓存机制。让我们逐步分析这个过程。

核心流程概览

复制代码
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 中没有,所以 sharedInstancenull
  • 继续进入创建流程
步骤 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");
    
    // ... 后续步骤
}

说明 :默认的 applicationStartupDefaultApplicationStartup,不做任何实际处理,主要用于性能监控。

步骤 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 属性,所以 dependsOnnull,这段代码跳过。

步骤 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,没有循环依赖,直接创建完成
  • 第三篇:ServiceAServiceB 存在循环依赖,需要在创建过程中处理循环依赖

总结 :通过以上 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() 方法中,会依次执行:

  1. 创建实例createBeanInstance() - 调用 ServiceA 的无参构造方法
  2. 提前暴露 :将 ServiceA 的工厂对象放入三级缓存
  3. 填充属性populateBean() - 这里会触发 ServiceB 的初始化!
  4. 初始化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的创建
}

关键流程

  1. ServiceA 创建流程

    • 创建 ServiceA 实例
    • 提前暴露到三级缓存
    • 填充属性时发现需要 ServiceB
    • 调用 getBean("serviceB")
  2. ServiceB 创建流程(被触发):

    • 创建 ServiceB 实例
    • 提前暴露到三级缓存
    • 填充属性时发现需要 ServiceA
    • 从三级缓存中获取 ServiceA 的早期引用(解决循环依赖!)
    • 完成 ServiceB 的创建
  3. 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-methodreplaced-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 中返回
  • 此时 ServiceAserviceB 属性还是 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);
    }
}

关键点pvsMutablePropertyValues 类型,包含了 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));
}

关键点

  1. PropertyValues 不是简单的实体类

    • PropertyValues 是一个接口,MutablePropertyValues 是其实现
    • 它包含了 Bean 的所有属性值,包括基本类型和 Bean 引用
    • 每个 PropertyValue 包含属性名和属性值(可能是 RuntimeBeanReference
  2. 遍历属性值

    • 通过 pvs.getPropertyValues() 获取所有属性值
    • 对于 ServiceA,会遍历到 serviceB 属性
  3. 解析属性值

    • 调用 valueResolver.resolveValueIfNecessary(pv, originalValue)
    • originalValueRuntimeBeanReference("serviceB") 时,会触发 getBean("serviceB") 的调用!
  4. 类型转换器

    • this.getCustomTypeConverter()null,使用默认的 bwBeanWrapperImpl)进行解析
    • 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 对象存储在 BeanDefinitionPropertyValues
  • 现在在属性填充阶段,需要将这个引用解析为实际的 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;
}

处理过程

  1. 获取 Bean 名称

    • RuntimeBeanReference 中获取 beanName"serviceB"
    • 调用 doEvaluate() 方法解析(可能是表达式,也可能是别名)
  2. 解析别名

    • 如果 "serviceB" 是别名,doEvaluate() 会通过别名映射表转换为实际的 Bean 名称
    • 对于我们的示例,"serviceB" 就是实际的 Bean 名称,不需要转换
  3. 回调 getBean

    • 调用 this.beanFactory.getBean(refName) 获取 ServiceB 实例
    • 这里会触发 ServiceB 的创建流程!
  4. 注册依赖关系

    • 调用 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);
    }
}

关键发现

  1. Bean 定义注册阶段

    • XML 中的 <property name="serviceB" ref="serviceB"/> 被解析为 RuntimeBeanReference("serviceB")
    • 存储在 BeanDefinitionPropertyValues
  2. Bean 创建阶段

    • populateBean() 时,遍历 PropertyValues
    • 发现 RuntimeBeanReference,调用 resolveReference() 解析
    • 通过 getBean("serviceB") 触发依赖 Bean 的创建
  3. 循环依赖的解决

    • ServiceA 创建时,提前暴露到三级缓存
    • ServiceB 创建时,需要 ServiceA,从三级缓存中获取早期引用
    • 完成 ServiceB 的创建后,返回给 ServiceA 使用

4. ServiceB 创建过程中的循环依赖处理

至此,关键的一环找到了!在 resolveReference() 方法中确实有回调 getBean("serviceB")。那么接下来更重要的就是:ServiceB 这个 Bean 创建过程中,解析到依赖 ServiceA 时会发生什么?

4.1 ServiceB 的创建流程(前半部分)

ServiceApopulateBean() 时调用 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;
}

处理过程

  1. 检查一级缓存

    • singletonObjects 中查找 "serviceA",返回 nullServiceA 还未完成创建)
  2. 检查是否正在创建

    • 调用 isSingletonCurrentlyInCreation("serviceA"),返回 trueServiceAsingletonsCurrentlyInCreation 中)
  3. 检查二级缓存

    • earlySingletonObjects 中查找 "serviceA",返回 null(还未放入二级缓存)
  4. 从三级缓存获取

    • singletonFactories 中获取 ServiceA 的工厂对象
    • 调用 singletonFactory.getObject() 获取 ServiceA 的早期引用
    • 这是解决循环依赖的关键!
  5. 升级到二级缓存

    • 将早期引用放入二级缓存 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 的早期引用(可能经过后置处理器处理)

为什么需要三级缓存?

  1. 一级缓存:存储最终完成的 Bean
  2. 二级缓存:避免重复调用工厂对象(性能优化)
  3. 三级缓存:存储工厂对象,可以获取经过后置处理器处理的早期引用(如 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 的所有属性值
  • 其中有一个 PropertyValuename="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;
}

处理过程详解

  1. 检查一级缓存

    • singletonObjects.get("serviceA") 返回 nullServiceA 还未完成创建)
  2. 检查是否正在创建

    • isSingletonCurrentlyInCreation("serviceA") 返回 true
    • 因为 ServiceAsingletonsCurrentlyInCreation 集合中
  3. 检查二级缓存

    • earlySingletonObjects.get("serviceA") 返回 null(第一次获取,还未放入二级缓存)
  4. 从三级缓存获取

    • singletonFactories.get("serviceA") 返回 ObjectFactory(匿名内部类对象)

    • 这个 ObjectFactory 是在步骤 18 中放入的:

      java 复制代码
      addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
  5. 调用工厂对象获取早期引用

    • singletonFactory.getObject() 调用匿名内部类的 get() 方法
    • 执行 getEarlyBeanReference("serviceA", mbd, serviceAInstance)
    • 返回 ServiceA 的早期引用(可能经过后置处理器处理)
  6. 升级到二级缓存

    • 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 的早期引用被返回给 ServiceB
  • ServiceBserviceA 属性被注入这个早期引用
  • 虽然 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;
}

关键点

  • ServiceBserviceA 属性已经注入(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;
}

关键点

  • ServiceAserviceB 属性已经注入(ServiceB 实例,已完成创建)
  • ServiceA 完成初始化后,放入一级缓存 singletonObjects
  • 从二级缓存 earlySingletonObjects 中移除 "serviceA"

4.7 再往后看就和之前普通的 Bean 定义一样的逻辑了

后续流程

  1. initializeBean

    • 调用 invokeAwareMethods() - 如果实现了 Aware 接口
    • 调用 applyBeanPostProcessorsBeforeInitialization() - BeanPostProcessor 前置处理
    • 调用 invokeInitMethods() - 初始化方法
    • 调用 applyBeanPostProcessorsAfterInitialization() - BeanPostProcessor 后置处理
  2. 注册单例 Bean

    • 调用 addSingleton(beanName, singletonObject)
    • 放入一级缓存 singletonObjects
    • 从二级缓存和三级缓存中删除
  3. 返回 Bean 实例

    • 返回完全初始化好的 Bean 实例

与第一篇的区别

对比项 第一篇(UserService) 第三篇(ServiceA/ServiceB)
依赖关系 无依赖 循环依赖
属性填充 无属性注入 需要注入依赖 Bean
缓存使用 只使用一级缓存 使用三级缓存机制
创建流程 直接创建完成 需要处理循环依赖

关键发现

  1. 循环依赖的解决时机

    • populateBean() 阶段,当发现依赖的 Bean 正在创建时
    • 从三级缓存获取早期引用,而不是等待 Bean 完全创建完成
  2. 三级缓存的作用

    • 一级缓存:存储完全初始化好的 Bean
    • 二级缓存:存储早期引用(避免重复调用工厂对象)
    • 三级缓存:存储工厂对象(可以获取经过后置处理器处理的早期引用)
  3. 为什么需要三级缓存

    • 如果只有两级缓存,无法获取经过后置处理器处理的早期引用(如 AOP 代理)
    • 三级缓存通过工厂对象延迟获取,可以应用后置处理器

5. 总结

5.1 循环依赖解决的核心机制

三级缓存机制

  1. 一级缓存 singletonObjects

    • 存储完全初始化好的单例 Bean
    • 最终的目标缓存
  2. 二级缓存 earlySingletonObjects

    • 存储提前暴露的单例 Bean(早期引用)
    • 用于避免重复从三级缓存获取(性能优化)
  3. 三级缓存 singletonFactories

    • 存储单例 Bean 的工厂对象(ObjectFactory
    • 用于获取 Bean 的早期引用(可能经过后置处理器处理)

解决流程

复制代码
ServiceA创建 → 提前暴露到三级缓存 → 填充属性时发现需要ServiceB
    ↓
ServiceB创建 → 提前暴露到三级缓存 → 填充属性时发现需要ServiceA
    ↓
从三级缓存获取ServiceA的早期引用 → 升级到二级缓存
    ↓
完成ServiceB的创建 → 返回给ServiceA
    ↓
完成ServiceA的创建 → 放入一级缓存

5.2 关键步骤总结

ServiceA 的创建流程

  1. 步骤 1-9doGetBean() 的前期准备

    • 解析 Bean 名称、检查缓存、标记正在创建等
  2. 步骤 10-18:进入创建流程

    • 创建 ServiceA 实例
    • 提前暴露到三级缓存(关键!)
  3. 步骤 19-21:填充属性

    • 发现需要 ServiceB
    • 调用 getBean("serviceB") 触发 ServiceB 的创建

ServiceB 的创建流程

  1. 步骤 1-18 :与 ServiceA 类似的创建流程

    • 创建 ServiceB 实例
    • 提前暴露到三级缓存
  2. 步骤 19-22:填充属性

    • 发现需要 ServiceA
    • 调用 getBean("serviceA")(第二次调用)
  3. 步骤 23-24:从三级缓存获取早期引用

    • 检查一级缓存:null(还未完成)
    • 检查是否正在创建:true
    • 从三级缓存获取 ObjectFactory
    • 调用工厂对象获取早期引用
    • 放入二级缓存,从三级缓存删除
  4. 步骤 25-37:完成创建

    • ServiceB 完成属性填充和初始化
    • ServiceA 完成属性填充和初始化
    • 放入一级缓存

5.3 与第一篇、第二篇的对比

对比项 第一篇(UserService) 第二篇(别名获取) 第三篇(循环依赖)
场景 最简单的 Bean 通过别名获取已缓存的 Bean 单例 Bean 的循环依赖
依赖关系 无依赖 无依赖 循环依赖(ServiceA ↔ ServiceB)
缓存使用 只使用一级缓存 只使用一级缓存 使用三级缓存机制
执行步骤 30 个步骤 3 个步骤 37+ 个步骤
关键机制 Bean 创建流程 别名转换 + 缓存查找 三级缓存解决循环依赖
性能 需要创建 Bean O(1) 缓存查找 需要处理循环依赖

5.4 关键发现

  1. 自动注入的 Bean 初始化时机

    • 位置populateBean() 方法中
    • 具体方法BeanDefinitionValueResolver.resolveReference()
    • 触发方式 :调用 beanFactory.getBean(refName) 获取依赖的 Bean
    • 时机:在 Bean 实例创建之后,属性填充阶段
  2. 循环依赖的解决条件

    • 必须是单例 Beanscope="singleton"
    • 必须允许循环依赖(allowCircularReferences = true
    • 必须使用属性注入(不能是构造器注入)
  3. 三级缓存的设计原因

    • 一级缓存:存储最终完成的 Bean
    • 二级缓存:避免重复调用工厂对象(性能优化)
    • 三级缓存:存储工厂对象,可以获取经过后置处理器处理的早期引用(如 AOP 代理)
  4. 为什么需要三级缓存而不是两级

    • 如果只有两级缓存,无法获取经过后置处理器处理的早期引用
    • 三级缓存通过工厂对象延迟获取,可以在获取时应用后置处理器
    • 这对于 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 注意事项

  1. 构造器注入不支持循环依赖

    • 构造器注入在实例化之前就需要依赖的 Bean
    • 此时 Bean 还未创建,无法提前暴露到三级缓存
    • 因此构造器注入的循环依赖会抛出异常
  2. 原型 Bean 不支持循环依赖

    • 原型 Bean 每次获取都创建新实例
    • 无法通过缓存机制解决循环依赖
    • 会抛出 BeanCurrentlyInCreationException 异常
  3. 循环依赖的限制

    • 必须是单例 Bean
    • 必须使用属性注入
    • 必须允许循环依赖(allowCircularReferences = true

5.7 核心要点回顾

  1. 自动注入的触发时机

    • populateBean() 方法中,通过 BeanDefinitionValueResolver.resolveReference() 触发
    • 调用 getBean() 获取依赖的 Bean,形成递归调用
  2. 循环依赖的解决机制

    • 通过三级缓存机制,在 Bean 还未完全初始化时提前暴露早期引用
    • 当依赖的 Bean 正在创建时,从三级缓存获取早期引用
    • 完成依赖注入后,继续完成 Bean 的初始化
  3. 三级缓存的设计

    • 一级缓存:存储最终完成的 Bean
    • 二级缓存:存储早期引用(性能优化)
    • 三级缓存:存储工厂对象(支持后置处理器处理)
  4. 关键方法

    • addSingletonFactory():将 Bean 的工厂对象放入三级缓存
    • getSingleton(beanName):从三级缓存获取早期引用
    • resolveReference():解析 Bean 引用,触发依赖 Bean 的创建

相关推荐
IT技术分享社区2 小时前
数据库实战:MySQL多表更新JOIN操作的底层原理与性能调优指南
数据库·mysql·程序员
Wokoo72 小时前
开发者AI大模型学习与接入指南
java·人工智能·学习·架构
电摇小人2 小时前
我的“C++之旅”(博客之星主题作文)
java·开发语言
资生算法程序员_畅想家_剑魔3 小时前
Java常见技术分享-23-多线程安全-总结
java·开发语言
UrSpecial3 小时前
InnoDB存储引擎
数据库·mysql
萧曵 丶3 小时前
ArrayList 和 HashMap 自动扩容机制详解
java·开发语言·面试
㳺三才人子3 小时前
初探 Spring Framework OncePerRequestFilter
spring boot·spring·junit
gjc5923 小时前
MySQL隐蔽 BUG:组合条件查询无故返回空集?深度排查与规避方案
android·数据库·mysql·bug
这是程序猿3 小时前
基于java的ssm框架学生作业管理系统
java·开发语言·spring boot·spring·学生作业管理系统