Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Spring通过三级缓存解决单例模式循环依赖的步骤好像是错的 #276

Open
iamarealgoodman opened this issue Aug 29, 2024 · 0 comments

Comments

@iamarealgoodman
Copy link

Spring通过三级缓存解决单例模式循环依赖的步骤好像是错的,好像应该是:

在 Spring 容器中,三级缓存机制用于解决单例模式下 bean 的循环依赖问题。以下是三级缓存解决循环依赖的详细流程:

1. 创建 bean 实例

当 Spring 容器开始创建一个 bean 时,首先会通过反射创建一个原始的 bean 实例。

2. 将 bean 实例放入三级缓存

在创建完原始 bean 实例后,Spring 容器会立即将这个实例包装成一个 ObjectFactory,并将其放入三级缓存(singletonFactories)中。ObjectFactory 是一个工厂对象,它能够提供 bean 的早期引用。

singletonFactories.put(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));

3. 填充属性

Spring 尝试为这个原始的 bean 实例填充属性,如果此时发现依赖的属性还未创建,则会尝试创建依赖的 bean。

4. 检查依赖的 bean 是否已经创建

在创建依赖的 bean 时,Spring 容器会重复上述步骤。如果在创建依赖 bean 的过程中又需要依赖原始的 bean,则会触发以下流程:

5. 检查一级缓存

Spring 首先检查一级缓存(singletonObjects)中是否已经存在所需的 bean 实例。如果存在,直接返回。

6. 检查二级缓存

如果一级缓存中没有找到,Spring 接着检查二级缓存(earlySingletonObjects)中是否有早期引用。如果存在,直接返回。

7. 检查三级缓存

如果二级缓存中也没有找到,Spring 会检查三级缓存(singletonFactories)是否有对应的 ObjectFactory。如果有,Spring 会通过 ObjectFactory 获取早期引用,并将其放入二级缓存,同时从三级缓存中移除。

ObjectFactory<?> singletonFactory = singletonFactories.get(beanName);
if (singletonFactory != null) {
    Object earlySingletonReference = singletonFactory.getObject();
    // 将早期引用放入二级缓存
    earlySingletonObjects.put(beanName, earlySingletonReference);
    // 从三级缓存中移除
    singletonFactories.remove(beanName);
    return earlySingletonReference;
}

8. 完成属性填充和初始化

此时,原始 bean 和其依赖的 bean 都有了早期引用,可以继续进行属性填充和初始化。

9. 将完全初始化的 bean 放入一级缓存

当 bean 完成所有初始化步骤后,Spring 会将其从二级缓存中移除,并将其放入一级缓存,供后续使用。

addSingleton(beanName, singletonObject);

总结

通过上述流程,Spring 容器能够解决单例模式下 bean 的循环依赖问题。需要注意的是,这个机制依赖于以下条件:

  • bean 必须是单例模式。
  • bean 的创建过程不涉及 AOP,或者 AOP 的代理是通过三级缓存中的 ObjectFactory 生成的。
    如果这些条件不满足,Spring 可能无法解决循环依赖问题。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant