本文介绍: Spring循环依赖Spring循环依赖简单说就是自己依赖自己,或者和别的Bean相互依赖。鸡和蛋只有单例的Bean才存在循环依赖的情况,

 15.说说循环依赖?

什么循环依赖?

Spring循环依赖

Spring 循环依赖:简单说就是自己依赖自己,或者和别的Bean相互依赖。

鸡和蛋

只有单例的Bean才存在循环依赖的情况,原型(Prototype)情况下,Spring会直接抛出异常原因简单,AB循环依赖,A实例化的时候,发现依赖B,创建B实例创建B的时候发现需要A,创建A1实例……无限套娃,直接把系统干垮。

Spring可以解决哪些情况的循环依赖?

Spring不支持基于构造注入的循环依赖,但是假如AB循环依赖,如果一个构造注入一个setter注入呢?

看看几种情形:

循环依赖的几种情形

第四种可以而第五种不可以的原因是 Spring 在创建 Bean 时默认会根据自然排序进行创建,所以 A 会先于 B 进行创建

所以简单总结,当循环依赖的实例采用setter方法注入的时候,Spring可以支持,都采用构造器注入的时候,不支持构造器注入和setter注入同时存在的时候,看天。

16.那Spring怎么解决循环依赖的呢?

PS:其实正确答案开发人员做好设计,别让Bean循环依赖,但是没办法,面试官不想听这个。

我们知道单例Bean初始化完成,要经历三步:

Bean初始化步骤

注入就发生在第二步,属性赋值结合这个过程,Spring 通过三级缓存解决了循环依赖:

  1. 一级缓存 : Map<String,ObjectsingletonObjects,单例池,用于保存实例化、属性赋值(注入)、初始化完成的 bean 实例

  2. 二级缓存 : Map<String,ObjectearlySingletonObjects,早期曝光对象用于保存实例化完成的 bean 实例

  3. 三级缓存 : Map<String,ObjectFactory<?>> singletonFactories,早期曝光对象工厂用于保存 bean 创建工厂以便于后面扩展有机会创建代理对象

三级缓存

我们来看一下三级缓存解决循环依赖的过程

当 A、B 两个类发生循环依赖时:

A实例的初始化过程

  1. 创建A实例,实例化的时候把A对象⼯⼚放⼊三级缓存表示A开始实例化了,虽然我这个对象还不完整,但是先曝光出来让大家知道

    1

  2. A注⼊属性时,发现依赖B,此时B还没有被创建出来,所以去实例化B

  3. 同样,B注⼊属性发现依赖A,它就会从缓存里找A对象。依次从⼀级到三级缓存查询A,从三级缓存通过对象⼯⼚拿到A,发现A虽然不太完善,但是存在,把A放⼊⼆级缓存,同时删除三级缓存中的A,此时,B已经实例化并且初始化完成,把B放入⼀级缓存。

    2

  4. 接着A继续属性赋值,顺利从⼀级缓存拿到实例化且初始化完成的B对象,A对象创建也完成,删除⼆级缓存中的A,同时把A放⼊⼀级缓存

  5. 最后,⼀级缓存中保存着实例化、初始化都完成的A、B对象

5

所以,我们知道为什么Spring能解决setter注入的循环依赖了,因为实例化和属性赋值是分开的,所以里面操作空间。如果都是构造器注入的化,那么都得在实例化这一步完成注入,所以自然是无法支持了。

17.为什么要三级缓存?⼆级不⾏吗?

不行,主要是为了⽣成代理对象。如果是没有代理的情况下,使用二级缓存解决循环依赖也是OK的。但是如果存在代理,三级没有问题二级就不行了。

因为三级缓存中放的是⽣成具体对象的匿名内部类,获取Object的时候,它可以⽣成代理对象,也可以返回普通对象。使⽤三级缓存主要是为了保证不管什么时候使⽤的都是⼀个对象。

假设只有⼆级缓存的情况,往⼆级缓存中放的显示⼀个普通的Bean对象,Bean初始化过程中,通过 BeanPostProcessor 去⽣成代理对象之后,覆盖掉⼆级缓存中的普通Bean对象,那么可能就导致取到的Bean对象不一致了。

二级缓存不行的原因

18.@Autowired实现原理

实现@Autowired的关键是:AutowiredAnnotationBeanPostProcessor

在Bean的初始化阶段,会通过Bean后置处理器来进行一些前置和后置的处理

实现@Autowired的功能,也是通过后置处理器来完成的。这个后置处理器就是AutowiredAnnotationBeanPostProcessor。

原文地址:https://blog.csdn.net/m0_63722685/article/details/125890757

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_21258.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注