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
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

shangjg3

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值