spring循环依赖

薄洪涛2年前JAVA6373

什么是循环依赖?

很简单,就是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

相关文章

springboot 数据校验

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

spring AOP概念及应用场景

spring AOP概念及应用场景

概念面向切面编程,通过预编译和运行期间动态代理实现在不修改源代码的情况下给程序动态统一添加功能的技术思想就是把很多类中对象中横切问题点,从业务逻辑中分离出来,达到解耦的目的,增加代码的重用性,提高开发...

docker-swarm部署java项目

技术栈Java 版本: 17Spring Boot 版本: 3.xMyBatis-Plus: 简化 MyBatis 操作的增强工具PostgreSQL: 关系型数据库Redis: 分布式缓存解决方案R...

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

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

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

centos安装java环境

centos安装java环境

很多工具(比如Lucene )都要依赖java环境,所以我在服务器上装了一个jdk,然后在这篇文章中记录下安装的步骤;当我们修改程序并通过SVN上传到服务器后环境:  &...

谈谈你对IOC的理解

 ioc容器实际上就是个map(key,value),⾥⾯存的是各种对象(在xml⾥配置的bean节点、 @repository、@service、@controller、@componen...

评论列表

发表评论    

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