spring循环依赖

薄洪涛2年前JAVA6624

什么是循环依赖?

很简单,就是A对象依赖了B对象,B对象依赖了A对象

在Spring中,⼀个对象并不是简单new出来了,⽽是会经过⼀系列的Bean的⽣命周期,就是因为 Bean的⽣命周期所以才会出现循环依赖问题。当然,在Spring中,出现循环依赖的场景很多,有的场景 Spring⾃动帮我们解决了,⽽有的场景则需要程序员来解决

Bean的⽣命周期指的就是:在Spring中,Bean是如何⽣成的?
被Spring管理的对象叫做Bean。

Bean的⽣成步骤
  1. Spring扫描class得到BeanDefinition

  2. 根据得到的BeanDefinition去⽣成bean

  3. ⾸先根据class推断构造⽅法

  4. 根据推断出来的构造⽅法,反射,得到⼀个对象(暂时叫做原始对象)

  5. 填充原始对象中的属性(依赖注⼊)

  6. 如果原始对象中的某个⽅法被AOP了,那么则需要根据原始对象⽣成⼀个代理对象

  7. 把最终⽣成的代理对象放⼊单例池(源码中叫做singletonObjects)中,下次getBean时就直接从单例
    池拿即可

产生场景

ABean创建-->依赖了B属性-->触发BBean创建--->B依赖了A属性--->需要ABean(但ABean还在创建过程中)

从⽽导致ABean创建不出来,BBean也创建不出来。 这是循环依赖的场景

image.png


三级缓存

在Spring中,通过某些机制帮开发者解决了部分循环依赖的问题, 这个机制就是三级缓存,三级缓存是通⽤的叫法。

⼀级缓存为:singletonObjects

⼆级缓存为:earlySingletonObjects

三级缓存为:singletonFactories

image.png

A的Bean在创建过程中,在进⾏依赖注⼊之前,先把A的原始Bean放⼊缓存(提早暴露,只要放到缓存了,其他Bean需要时就可以从缓存中拿了),放⼊缓存后,再进⾏依赖注⼊,此时A的Bean依赖了B的Bean,如果B的Bean不存在,则需要创建B的Bean,⽽创建B的Bean的过程和A⼀样,也是先创建⼀个B的原始对象,然后把B的原始对象提早暴露出来放⼊缓存中,然后在对B的原始对象进⾏依赖注⼊A,此时能从缓存中拿到A的原始对象(虽然是A的原始对象,还不是最终的Bean),B的原始对象依赖注⼊完了之后,B的⽣命周期结束,那么A的⽣命周期也能结束。

因为整个过程中,都只有⼀个A原始对象,所以对于B⽽⾔,就算在属性注⼊时,注⼊的是A原始对象,也没有关系,因为A原始对象在后续的⽣命周期中在堆中没有发⽣变化。

注意:


标签: spring

相关文章

微信H5支付安卓提示"商家参数格式有误请联系商家解决"

微信H5支付安卓提示"商家参数格式有误请联系商家解决"

今天遇到一个恼火的问题,我们对接微信的H5支付,采用了前后端分离,后端接口返回了支付的url,ios正常唤起微信支付,android却始终提示商家参数格式有误请联系商家解决,如图按照微信提供的文档,我...

springboot 数据校验

使用import javax.validation.constraints.NotNull import javax.validation.constraints.Size cl...

接口熔断器resilience4j的使用

pom引入<!-- 熔断器 : https://mvnrepository.com/artifact/io.github.resilience4j/resilien...

spring中什么情况下事务会失效?

事务失效的场景?权限问题,@Transactional 修饰的方法必须为public方法用final修饰或者是static方法,spring事务底层使用了aop,也就是通过jdk动态代理或者cglib...

RabbitMq交换机类型

RabbitMq交换机类型

direct路由键和队列名完全匹配,才可以消费如果绑定时设置了routing key为”abc”,那么客户端提交的消息,只有设置了key为”abc”的才会投递到队列fanout还有一种不需要key的,...

Springboot+Kotlin的搭建

Springboot+Kotlin的搭建

不少公司觉得php的性能较低,于是采用java做逻辑处理,php做表现层的做法,个人觉得对于业务量比较复杂,安全性要求较高的项目,可以采用此类做法;于是我学着搭建了一个基于spring boot的接口...

评论列表

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。