Spring循环依赖检查算法分析

        Spring在注入bean的时候会做循环依赖检查,例如A依赖B,B依赖C,C依赖A,这就形成了一个循环依赖,Spring会抛出异常。

        那么Spring是怎么做到循环依赖检查的呢?我们先来考虑,Spring是如何实现注入功能的,在注入A之前,如果A依赖B那么需要先注入B,然后依次类推下去,明显,这是一个递归的调用,Spring在其BeanFactory的实现类中,对getBean方法递归调用实现注入,代码如下:

// spring 依赖注入 DFS
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
  for (String dependsOnBean : dependsOn) {
    if (isDependent(beanName, dependsOnBean))
   {
     // 有循环依赖,抛异常
   }
   //注册dependsOnBean 的前驱为beanName
    regirsert(dependsOnBean,beanName)
    getBean(dependsOnBean);// 递归调用
  }
}

         如上所示,这其实是一个有向图的深度遍历算法,红色部分实现了循环依赖检查,有兴趣的同学可以自己去看下具体的实现,我这里仅给出形式化解释和伪代码。

        到这里,这个问题就转化为有向图是否存在环的问题。isDependent方法参数传入两个节点,如果有环返回true,否则返回false。我来尝试形式化的描述这个问题的解

有向图环检查形式化描述 写道
->符号记为一个有向的连接
我们尝试连接A->B,那么以下两种情况可判断为有环:
1.如果有B->A,
2.存在某个X->A使B->X。

 算法采用一个map来存某个节点的所有前驱节点,以下是伪代码描述

写道
// 尝试A->B,如果存在B->A返回true
isDependent(String A, String B, Set<String> alreadySeen) {
        if alreadySeen.Has(A) then // 略过所有已访问过的前驱
            return false;
        if map = null then
            return false;
        if map.get(A).has(B) then // 如果有B->A则有环
            return true;
       for X in map.get(A)// 寻找A的所有前驱,X->A
            if isDependent(X,B) then // 如果有B->X则有环
       return true;
       alreadySeen.add(A)// 标记为已访问
       return false;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值