网创优客建站品牌官网
为成都网站建设公司企业提供高品质网站建设
热线:028-86922220
成都专业网站建设公司

定制建站费用3500元

符合中小企业对网站设计、功能常规化式的企业展示型网站建设

成都品牌网站建设

品牌网站建设费用6000元

本套餐主要针对企业品牌型网站、中高端设计、前端互动体验...

成都商城网站建设

商城网站建设费用8000元

商城网站建设因基本功能的需求不同费用上面也有很大的差别...

成都微信网站建设

手机微信网站建站3000元

手机微信网站开发、微信官网、微信商城网站...

建站知识

当前位置:首页 > 建站知识

Spring如何解决循环依赖的问题-创新互联

前言

创新互联建站长期为1000多家客户提供的网站建设服务,团队从业经验10年,关注不同地域、不同群体,并针对不同对象提供差异化的产品和服务;打造开放共赢平台,与合作伙伴共同营造健康的互联网生态环境。为依安企业提供专业的成都网站设计、成都网站建设,依安网站改版等技术服务。拥有十多年丰富建站经验和众多成功案例,为您定制开发。

在面试的时候这两年有一个非常高频的关于spring的问题,那就是spring是如何解决循环依赖的。这个问题听着就是轻描淡写的一句话,其实考察的内容还是非常多的,主要还是考察的应聘者有没有研究过spring的源码。但是说实话,spring的源码其实非常复杂的,研究起来并不是个简单的事情,所以我们此篇文章只是为了解释清楚Spring是如何解决循环依赖的这个问题。

什么样的依赖算是循环依赖?

用过Spring框架的人都对依赖注入这个词不陌生,一个Java类A中存在一个属性是类B的一个对象,那么我们就说类A的对象依赖类B,而在Spring中是依靠的IOC来实现的对象注入,也就是说创建对象的过程是IOC容器来实现的,并不需要自己在使用的时候通过new关键字来创建对象。
那么当类A中依赖类B的对象,而类B中又依赖类C的对象,最后类C中又依赖类A的对象的时候,这种情况最终的依赖关系会形成一个环,这就是循环依赖。

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

循环依赖的类型

根据注入的时机可以分为两种:

构造器循环依赖

依赖的对象是通过构造方法传入的,在实例化bean的时候发生。

赋值属性循环依赖

依赖的对象是通过setter方法传入的,对象已经实例化,在属性赋值和依赖注入的时候发生。
构造器循环依赖,本质上是无解的,实例化A的时候调用A的构造器,发现依赖了B,又去实例化B,然后调用B的构造器,发现又依赖的C,然后调用C的构造器去实例化,结果发起C的构造器里依赖了A,这就是个死循环无解。所以Spring也是不支持构造器循环依赖的,当发现存在构造器循环依赖时,会直接抛出BeanCurrentlyInCreationException 异常。
赋值属性循环依赖,Spring只支持bean在单例模式下的循环依赖,其他模式下的循环依赖Spring也是会抛出BeanCurrentlyInCreationException 异常的。Spring通过对还在创建过程中的单例bean,进行缓存并提前暴露该单例,使得其他实例可以提前引用到该单例bean。

Spring为什么只支持单例模式下的bean的赋值情况下的循环依赖

在prototype的模式下的bean,使用了一个ThreadLocal变量prototypesCurrentlyInCreation来记录当前线程正在创建中的bean,这个变量在AbtractBeanFactory类里。在创建前用beanName记录bean,在创建完成后删除bean。在prototypesCurrentlyInCreation里采用了一个Set对象来存储正在创建中的bean。我们都知道Set是不允许存在重复对象的,这样就能保证同一个bean在一个线程中只能有一个正在创建。
下面是prototypesCurrentlyInCreation变量在删除bean时的操作,在AbtractBeanFactorybeforePrototypeCreation操作里。

protected void afterPrototypeCreation(String beanName) {
  Object curVal = this.prototypesCurrentlyInCreation.get();
  if (curVal instanceof String) {
   this.prototypesCurrentlyInCreation.remove();
  }
  else if (curVal instanceof Set) {
   Set beanNameSet = (Set) curVal;
   beanNameSet.remove(beanName);
   if (beanNameSet.isEmpty()) {
    this.prototypesCurrentlyInCreation.remove();
   }
  }
 }

当前标题:Spring如何解决循环依赖的问题-创新互联
本文路径:http://bjjierui.cn/article/dcdhhj.html

其他资讯