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。
我们尝试连接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;
}
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;
}
相关推荐
Spring循环依赖debug源码图
Spring循环依赖.vsdx
Spring源码最难问题:当Spring AOP遇上循环依赖.docx
spring bean循环依赖时序图详细的描述了spring的循环依赖关系,帮我们快速了解spring是如何优雅的进行处理的
Spring三级缓存解决循环依赖.pdf
Spring依赖注入检查,适合初学者进一步了解Spring框架。
Spring集成SpringSecurity依赖包.也有springMVC的依赖包,直接下载引入就可用
spring 2.5依赖包
《spring源码之循环依赖和三级缓存》整理,本人水平有限,从网上找的资料整合之后做的,请辩证的看待其中内容。
Java使用Maven导入Spring依赖
Spring框架依赖jar包,其中最小依赖包:org.springframework.core、org.springframework.context、org.springframework.beans、org.springframework.asm、org.springframework.expression、...
Spring框架作为Java企业级应用的核心,其解决循环依赖的能力是其健壮性和灵活性的关键体现。循环依赖,即两个或多个组件相互依赖,常在大型应用中遇见。Spring通过三级缓存和AOP代理机制巧妙处理这一挑战。首先,一...
springaop依赖的jar包,spring版本2.5.6,如果需要,可以下载使用,欢迎各位评论指出不足
Spring相关依赖包,(spring-framework-3.0.2.RELEASE-dependencies)
主要介绍了简单了解Spring循环依赖解决过程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
1. 循环依赖检查 无论单例还是原型模式(下文①代表图中步骤1),spring都有对应的集合保存当前正在创建的beanName,标识该beanName正在被创建。在bean创建前,①检测当前bean是否在创建中,如果不在创建中则②将...
在开发中,可能经常出现这种情况,只是我们平时并没有注意到原来我们写的两个类、甚至多个类相互依赖了,为什么注意不到呢?...这一切都是Spring的功劳,它在后面默默的为我们解决了循环依赖的问题。
主要介绍了详解Spring循环依赖的解决方案,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
第一种:构造器参数循环依赖 Spring容器会将每一个正在创建的Bean 标识符放在一个“当前创建Bean池”中,Bean标识符在创建过程中将一直保持在这个池中。 因此如果在创建Bean过程中发现自己已经在“当前创建Bean池”...
Spring mvc依赖包 Spring mvc都做了些什么 Controller为中心完成对系统流程的控制管理 从请求中搜集数据 对传入的参数进行验证 将结果返回给视图 针对不同的视图提供不同的解决方案 针对jsp视图技术提供标签库 拦截...