Spring-循环依赖

预备知识

循环依赖开关(方法) - AbstractAutowireCapableBeanFactory#setAllowCircularReferences

  • 单例工程(属性) - DefaultSingletonBeanRegistry#singletonFactories
  • 获取早期未处理Bean (方法) - AbstractAutowireCapableBeanFactory#getEarlyBeanReference
  • 早期未处理Bean (属性) - DefaultSingletonBeanRegistry#earlySingletonObjects

循环依赖处理流程

案例代码:

@Component
public class ClassRoom {
    @Autowired
    private Collection<Student> students;

    public Collection<Student> getStudents() {
        return students;
    }

    public void setStudents(Collection<Student> students) {
        this.students = students;
    }
}
@Component
public class Student {
    @Autowired
    private ClassRoom classRoom;

    public ClassRoom getClassRoom() {
        return classRoom;
    }

    public void setClassRoom(ClassRoom classRoom) {
        this.classRoom = classRoom;
    }
}

这个例子ClassRoom里面注入了Student,Student里面又注入了ClassRoom。

首先要确保我们的循环依赖是单例的,然后再初始化单例Bean的时候会调用doGetBean方法,然后进入AbstractBeanFactory#doGetBean方法:
在这里插入图片描述
在getSington方法里面beforeSingletonCreation,有这样一个方法,这个方法会将当前正在创建的单例Bean放到singletonsCurrentlyInCreation中:
在这里插入图片描述
接着会调用我们拉姆达表达式穿进来的工厂createBean获取Bean,会判断是不是正在创建的Bean
在这里插入图片描述
如果是的话(前面在beforeSingletonCreation将当前创建的Bean放到了singletonsCurrentlyInCreation所以这里肯定是),会调用addSingletonFactory,会传进去一个拉姆达表达式:
在这里插入图片描述
这个时候singletonFactories就会存贮,并且earlySingletonObjects如果存在会移除这个Bean,同时将这个Bean放到已注册中:
在这里插入图片描述
接着就是这个Bean的populateBean逻辑,对依赖进行注入会处理依赖doResolveDependency:
在这里插入图片描述
由于我们注入Students是一个集合,所以会走multipleBeans这个处理:
在这里插入图片描述
这个时候又去getBean了,这个和我们上面ClassRoom走的是一样的流程,这个时候已经有两个了:
在这里插入图片描述
在Student注入的时候发现注入的字段又需要ClassRoom,于是又会去resolveDependency:
在这里插入图片描述
这个时候earlySingletonObjects里面没有,所以拿到了我们上面的singletonFactories中的singleFactory了,在拿到Bean以后就将singletonFactories中的移除了,同时将它放到earlySingletonObjects:
在这里插入图片描述
然后将这个ClassRoom的Bean注入到Student中:
在这里插入图片描述
我们可以看到这个时候ClassRoom里面是没有注入Students的:
在这里插入图片描述
接下来就是调用了addSington,里面如果判断是新创建的Sington做了这样几件事情:1)移除将当前Bean放到singtonObjects中 2)将singtonFactories中的singleFactory移除
在这里插入图片描述
然后回到了ClassRoom,这个时候Student的Bean已经进行了创建,进行注入即可。同时将这个Bean从创建中进行移除。
在这里插入图片描述
这就解决了循环依赖,我的理解是通过Map存储早期的Bean,然后注入的也是早期的Bean,等到它依赖的Bean完成注入的时候,注入的早期的Bean的引用也会发生变化,类似于一个延迟加载。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值