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

  1. 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
  2. 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  3. 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
  4. 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
  5. 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们
  6. 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
  7. 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
Spring如何处理循环依靠的问题 2021-10-12 ? ? ? ? 在关于Spring的面试中,我们经常会被问到一个问题,就是Spring是如何处理循环依靠的问题的。这个问题算是关于Spring的一个高频面试题,由于假如不刻意研读,信任即便读过源码,面试者也不肯定能够一下子思考出个中奇特。本文次要针对这个问题,从源码的角度对其实现原理进行讲解。 1. 过程演示 ????????关于Spring bean的创建,其本质上还是一个对象的创建,既然是对象,读者伴侣肯定要明白一点就是,一个完整的对象包含两部分:当前对象实例化和对象属性的实例化。在Spring中,对象的实例化是通过反射实现的,而对象的属性则是在对象实例化之后通过肯定的方式设置的。这个过程可以依据如下方式进行理解: ????????理解这一个点之后,对于循环依靠的理解就已经挂念一大步了,我们这里以两个类A和B为例进行讲解,如下是A和B的声明: @Component public class A { private B b; public void setB(B b) { this.b = b; } } @Component public class B { private A a; public void setA(A a) { this.a = a; } } ? ? ? ? 可以看到,这里A和B中各自都以对方为本人的全局属性。这里首先需要说明的一点是,Spring实例化bean是通过ApplicationContext.getBean()方法来进行的。假如要猎取的对象依靠了另一个对象,那么其首先会创建当前对象,然后通过递归的调用ApplicationContext.getBean()方法来猎取所依靠的对象,最终将猎取到的对象注入到当前对象中。这里我们以上面的首先初始化A对象实例为例进行讲解。首先Spring尝试通过ApplicationContext.getBean()方法猎取A对象的实例,由于Spring容器中还没有A对象实例,因而其会创建一个A对象,然后发觉其依靠了B对象,因而会尝试递归的通过ApplicationContext.getBean()方法猎取B对象的实例,但是Spring容器中此时也没有B对象的实例,因而其还是会先创建一个B对象的实例。读者需要留意这个时间点,此时A对象和B对象都已经创建了,并且保存在Spring容器中了,只不过A对象的属性b和B对象的属性a都还没有设置进去。在前面Spring创建B对象之后,Spring发觉B对象依靠了属性A,因而此时还是会尝试递归的调用ApplicationContext.getBean()方法猎取A对象的实例,由于Spring中已经有一个A对象的实例,虽然只是半成品(其属性b还未初始化),但其也还是目标bean,因而会将该A对象的实例前往。此时,B对象的属性a就设置进去了,然后还是ApplicationContext.getBean()方法递归的前往,也就是将B对象的实例前往,此时就会将该实例设置到A对象的属性b中。这个时候,留意A对象的属性b和B对象的属性a都已经设置了目标对象的实例了。读者伴侣可能会比较怀疑的是,前面在为对象B设置属性a的时候,这个A类型属性还是个半成品。但是需要留意的是,这个A是一个引用,其本质上还是最开头就实例化的A对象。而在上面这个递归过程的最终,Spring将猎取到的B对象实例设置到了A对象的属性b中了,这里的A对象其实和前面设置到实例B中的半成品A对象是同一个对象,其引用地址是同一个,这里为A对象的b属性设置了值,其实也就是为那个半成品的a属性设置了值。下面我们通过一个流程图来对这个过程进行讲解: ????????图中getBean()表示调用Spring的ApplicationContext.getBean()方法,而该方法中的参数,则表示我们要尝试猎取的目标对象。图中的黑色箭头表示一开头的方法调用走向,走到最终,前往了Spring中缓存的A对象之后,表示递归调用前往了,此时使用绿色的箭头表示。从图中我们可以很清楚的看到,B对象的a属性是在第三步中注入的半成品A对象,而A对象的b属性是在其次步中注入的成品B对象,此时半成品的A对象也就变成了成品的A对象,由于其属性已经设置完成了。 2. 源码讲解 ????????对于Spring处理循环依靠问题的方式,我们这里通过上面的流程图其实很简约就可以理解,需要留意的一个点就是,Spring是如何标记开头生成的A对象是一个半成品,并且是如何保存A对象的。这里的标记工作Spring是使用ApplicationContext的属性Set singletonsCurrentlyInCreat

文档评论(0)

bob157641554 + 关注
实名认证
文档贡献者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档