欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring循环依赖(缩略版)

程序员文章站 2023-12-27 10:25:45
...

Spring循环依赖问题也算是个老掉牙的问题,一搜一大把,这里纯粹是为了给自己做个笔记,所以写(水)一篇博客

那么为什么要叫缩略版呢,因为这里不打算分析Spring源码来讲了(主要是因为懒),能画图那就不分析代码

首先Spring创建一个对象分为了三步:实例化 -> 填充属性 -> 初始化
Spring循环依赖(缩略版)
那如果是在构造器中进行了循环依赖,假如A的构造器依赖于B,B的构造器中依赖于A,那么就类似于死锁了,Spring也救不了你

那么如果是使用setter方式的话呢?

@Component
public class A {
  private B b;
  public void setB(B b) {
    this.b = b;
  }
}

@Component
public class B {
  private A a;
  public void setA(A a) {
    this.a = a;
  }
}

那就不一样了,Spring默认构造的是对象单例,同时有三级缓存,singletonObjects(一级),earlySingletonObjects(二级),singletonFactories(三级),一级找不到就往下接着找,找到了的话就放入上一层中,这个应该很好理解吧

以上面的代码来画图说明一下setter方式是如何解决循环依赖的
Spring循环依赖(缩略版)
简单解释一下图中的步骤

  1. A实例化完成,接着属性填充的时候找不到B,所以去执行B的实例化
  2. B实例化完成,属性填充的时候去找A
  3. 一二三级缓存依次往下找,因为A还未初始化完成,所以一二级缓存都找不到,在三级缓存中找到了还未初始化完成的A
  4. B完成属性填充和初始化,将自己加入到了一级缓存中
  5. A接着进行属性填充,获取到了B,接着进行初始化,A初始化完成,Spring循环依赖解决

总结:Spring如果是构造器构注入的话,无法解决循环依赖(这里的构造器注入说的是两个循环依赖的类都使用构造器注入,如果按照上面代码的顺序,A使用setter注入,B使用构造器注入的话,也是可以解决循环依赖的);如果是setter注入的话,依靠Spring的对象生成步骤和一二三级缓存的机制可解决循环依赖

相关标签: 经典问题

上一篇:

下一篇: