laywin

  • 主页
  • 随笔
所有文章 关于我

laywin

  • 主页
  • 随笔

spring 如何解决循环依赖的问题

2024-01-02

很古老的一个问题,面试可能问的比较多,最近在排查问题的时间专门去跟踪了一下.

要解答这个问题,需要首先知道spring bean的创建流程:

  1. 实例化bean
    bean new 出来之后会放入singletonFactories中,singletonFactories是遇到循环依赖后,用来创建Bean的
  2. 设置bean的property
  3. 调用bean生命周期hook

完了之后bean会放入singletonObjects中.

举一个循环依赖的情况:

A依赖B, B依赖A

首先创建Bean A.

  1. 实例化 Bean A
  2. 将Bean A 放入 singletonFactories
  3. 设置Bean A的property, 这时候会去找Bean B, 发现Bean B并没有创建,同样走Bean A实例化的流程
  4. 实例化 Bean B
  5. 将Bean B 放入 singletonFactories
  6. 设置Bean B的property, 这时候会去找Bean A, 下面我们看一下查找过程:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 看 singletonObjects 中有没,singletonObjects是完全初始化好的
Object singletonObject = this.singletonObjects.get(beanName);
// 如果查找的bean正在创建过程中,继续往下走
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
// 看 earlySingletonObjects 中有没,earlySingletonObjects中的数据就是在这个方法后面放的
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
// 同步互斥
synchronized (this.singletonObjects) {
// Consistent creation of early reference within full singleton lock
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
// 注意 singletonFactories 中的数据在 bean new出来之后就会放
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// 将bean拿出来
singletonObject = singletonFactory.getObject();
// 放入 earlySingletonObjects 中
this.earlySingletonObjects.put(beanName, singletonObject);
// 从单例工厂中移除
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}

getSingleton 方法就是解决循环依赖的答案,在我们的例子中就是Bean B 在找Bean A的时候,其实Bean A并不是完全构造的,就是 Bean A的property还是设置完,但并不影响解决循环依赖.

赏

有鸡腿吃吗

微信

扫一扫,分享到微信

微信分享二维码
spring hook

Gitalking ...

© 2024 laywin
Hexo Theme Yilia by Litten
  • 所有文章
  • 关于我

tag:

  • springboot
  • 源码分析
  • 日常挖码
  • 分布书追踪
  • apm
  • 日志
  • zipkin
  • redis事务
  • cas
  • xxljob

    缺失模块。
    1、请确保node版本大于6.2
    2、在博客根目录(注意不是yilia根目录)执行以下命令:
    npm i hexo-generator-json-content --save

    3、在根目录_config.yml里添加配置:

      jsonContent:
        meta: false
        pages: false
        posts:
          title: true
          date: true
          path: true
          text: false
          raw: false
          content: false
          slug: false
          updated: false
          comments: false
          link: false
          permalink: false
          excerpt: false
          categories: false
          tags: true
    

laywin@yeah.net
@chongqing