栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring循环依赖的关键代码和流程示意图

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring循环依赖的关键代码和流程示意图

文章目录
  • 前言
  • 一、什么是循环依赖
  • 二、怎么解决问题
    • 三级缓存
  • 三、图解
  • 四、面试题
  • 总结


前言

该文章是看视频与书籍,用个人的理解话语完成。所以此文不是很细致,仅是作为关键点记忆。


提示:以下是本篇文章正文内容,内容如有错误,可在评论区回复

一、什么是循环依赖

A对象里,有属性B对象。B对象里,有属性A对象。
A.B对象互相引用,创建时,产生的问题。

public class A {
	private B b;
	
	public B getB() {
		return b;
	}

	public void setB(B b) {
		this.b = b;
	}
	
}

public class B {
	private A a;
	
	public A getA() {
		return a;
	}

	public void setA(A a) {
		this.a = a;
	}
}

二、怎么解决问题

Spring通过提前暴露对象(即完成实例化但未完成初始化的对象)的方式解决循环依赖问题。使用三级缓存,map结构来存储对象。

  1. 先从三级缓存中获取A.发现没有后,创建A对象,进行实例化,生成了半成品A对象
  2. 在进行A对象属性填充前,将A对象的lamdba表达式存入三级缓存。
  3. populateBean设置属性时,需要B对象。容器中没有,开始创建B对象。从新走回第一步,这回创建的是B对象。
  4. B对象实例化后,设置属性前,将B对象的lamdba表达式存入三级缓存
  5. B开始设置属性,需要A对象,这时会从缓存中取A,先从一级缓存,二级缓存,三级缓存来取,三级缓存中有,将执行A的lamdba表达式getEarlyBeanReference,获得A的半成品状态。填充B的属性值。B已经是完整状态。
  6. 然后将A半成品存入二级缓存,将A的lamdba表达式从三级缓存移除。
  7. 将完整的B存入一级缓存,并且删除二,三级缓存中的B。
  8. 可以将B赋值给A对象了,将A存入一级,并且删除二,三级的A。
三级缓存
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
	
	
	
	private final Map singletonObjects = new ConcurrentHashMap<>(256);

	
	
	private final Map> singletonFactories = new HashMap<>(16);

	
	
	private final Map earlySingletonObjects = new HashMap<>(16);
.....
}
三、图解

其中有部分关键代码。可自行打断点调试。

四、面试题

1、一二三级缓存分别存放什么状态对象?
一级:成品对象二级:半成品三级:lamdba表达式

2、如果只设置一级缓存能否解决循环依赖问题?
如果只有一级缓存,成品对象和半成品都需要存入一级缓存,没办法区分状态。

3、如果只有二级缓存能否解决循环依赖问题?
能解决。但是前提是不使用代理。三级缓存是为了解决代理过程中的循环依赖问题。

思考,那些地方用到了三级缓存?
addSingletonFactory(),向三级缓存存放属性值getSingleton():从三级缓存中获取属性值

4、如果一个对象需要被代理的话,在整个容器中,会存在几个当前对象的版本?
有2个版本
1、原始对象,直接通过反射创建出的对象
2、通过cglib或jdk的动态代理创建对象来的对象

5、到底那里被代理了,当添加了aop之后,跟刚刚的处理步骤哪里不一样?exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);原始bean可能被修改,返回了被代理的对象。

6、总结:每次我们获取对象的时候,是通过对象的name来获取Bean的,如果原始对象和代理对象同时存在的话,那我通过名字在进行获取的时候,应该用哪一个?
无法选择,其实还有最核心的点,你如何能够确认对象时候需要被引用?
使用lamdba表达式其实代表了一种回调机制,当需要使用当前对象的时候,通过lamdba表达式来最终返回一个确定的最终版本对象,而不需要判断有几个对象,因为是替换的过程,所以只能有一个。

7、这三级缓存的查找顺序是啥?
先找singletonObjects,earlySingletonObjects,singletonFactories


总结

这里是完整内容
https://www.processon.com/view/link/62b31877e401fd071e0f6d37


参考内容:

  • 《精通Spring+4.x++企业应用开发实战》
  • B站上的Spring视频
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/985898.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号