Spring 如何解决循环依赖问题

Spring 解决循环依赖问题的核心在于提前暴露一个已经创建完成的对象引用,而不是提前暴露一个未初始化的代理对象。Spring 使用的三级缓存机制就是实现这个目的的。

1.  单例对象的创建过程中遇到循环依赖,Spring 采取提前暴露引用的方式解决。

2.  三级缓存:singletonObjects、earlySingletonObjects、singletonFactories

3.  解决方法:

a.  当请求Bean时,如果Bean正在创建中,则先返回一个临时的代理对象(早期代理对象),这样可以允许其他Bean引用该Bean,形成一个引用链。

b.  当Bean创建完成后,原始对象被存储在singletonObjects中,早期引用则被移到earlySingletonObjects中。

c.  当Bean属性设置完成,最终调用Bean的完成初始化方法,此时原始对象会被再次放回singletonObjects中,早期引用对象被移除。

以下是一个简化的示例,展示了Spring如何通过三级缓存解决循环依赖问题:

// 假设有两个相互依赖的Bean
public class A {
    private B b;
    public void setB(B b) {
        this.b = b;
    }
    public B getB() {
        return b;
    }
}
 
public class B {
    private A a;
    public void setA(A a) {
        this.a = a;
    }
    public A getA() {
        return a;
    }
}
 
// 创建Bean的过程
ObjectFactory<A> aFactory = () -> a; // 提前暴露A的引用
ObjectFactory<B> bFactory = () -> b; // 提前暴露B的引用
 
// 创建A
if (a == null) {
    a = factoryMethod.createInstance(); // 创建A的实例
    beanFactory.registerDependentBean(BEAN_NAME, BEAN_NAME);
    beanFactory.registerDependentBean(BEAN_NAME, BEAN_NAME);
    aFactory = () -> a;
    singletonFactories.put(BEAN_NAME, aFactory);
    // 提前暴露A的引用,允许B创建过程中引用A
    earlySingletonObjects.put(BEAN_NAME, a);
    // 设置B依赖A
    a.setB(b);
}
 
// 创建B
if (b == null) {
    b = factoryMethod.createInstance(); // 创建B的实例
    beanFactory.registerDependentBean(BEAN_NAME, BEAN_NAME);
    beanFactory.registerDependentBean(BEAN_NAME, BEAN_NAME);
    bFactory = () -> b;
    singletonFactories.put(BEAN_NAME, bFactory);
    // 提前暴露B的引用,允许A创建过程中引用B
    earlySingletonObjects.put(BEAN_NAME, b);
    // 设置A依赖B
    b.setA(a);
}
 
// 完成初始化
a.setB(b);
b.setA(a);
 
// 最后,移除早期引用对象,原始对象被存储在singletonObjects中
earlySingletonObjects.remove(BEAN_NAME);
singletonFactories.remove(BEAN_NAME);

这个过程展示了Spring如何通过提前暴露引用来解决循环依赖的问题。在创建Bean的过程中,Spring会使用三级缓存来管理对象的创建过程,保证在创建过程中依然能够提供已经初始化完成的对象引用,从而解决循环依赖的问题。

相关推荐

  1. Spring循环依赖问题如何解决

    2024-07-16 05:46:02       31 阅读
  2. Spring 如何解决循环依赖问题

    2024-07-16 05:46:02       26 阅读
  3. Spring如何解决循环依赖

    2024-07-16 05:46:02       43 阅读
  4. Spring如何解决循环依赖

    2024-07-16 05:46:02       38 阅读
  5. Spring如何解决循环依赖

    2024-07-16 05:46:02       24 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-16 05:46:02       66 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-16 05:46:02       70 阅读
  3. 在Django里面运行非项目文件

    2024-07-16 05:46:02       57 阅读
  4. Python语言-面向对象

    2024-07-16 05:46:02       68 阅读

热门阅读

  1. Python小工具—txt转excel和word

    2024-07-16 05:46:02       20 阅读
  2. Matplotlib库学习之mpl_toolkits.mplot3d.Axes3D函数

    2024-07-16 05:46:02       26 阅读
  3. uniapp 如何实现路由拦截,路由守卫

    2024-07-16 05:46:02       22 阅读
  4. 健康管理平台的元宇宙革新

    2024-07-16 05:46:02       17 阅读
  5. Spring Batch批量处理数据

    2024-07-16 05:46:02       24 阅读
  6. lua package.path

    2024-07-16 05:46:02       23 阅读
  7. 【AI原理解析】—支持向量机原理

    2024-07-16 05:46:02       25 阅读
  8. C++面试

    C++面试

    2024-07-16 05:46:02      21 阅读
  9. 【Flask项目】文件分享系统(一)

    2024-07-16 05:46:02       28 阅读
  10. Barabási–Albert模型详解与Python代码示例

    2024-07-16 05:46:02       26 阅读