spring循环依赖

薄洪涛2年前JAVA6149

什么是循环依赖?

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

相关文章

docker-swarm部署java项目

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

设计模式之策略模式

在开始之前,我们先看一下一个令人不爽的写法if ($k == 0) {   // do something } ...

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

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

idea 部署Tomcat服务器

idea 部署Tomcat服务器

一、创建一个web项目1.file-new project,选择正确的jdk版本后(没配置的可以先自行google配置),next2.next3.输入项目名字和路径二,创建Module1.鼠标点中项目...

RabbitMq交换机类型

RabbitMq交换机类型

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

centos安装java环境

centos安装java环境

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

评论列表

发表评论    

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