循环依赖问题,三级缓存的map结构

创建A对象

给A对象进行实例化操作:Map:A 的半成品,查询是否有B;B的半成品;B成品,A成品

给A对象的B属性赋值

判断容器中是否有B对象

有:直接赋值

没有

创建B对象

给B对象进行实例化操作

给B对象的A属性赋值

判断容器中是否有A对象

没有

创建A对象... 循环开启...

将对象按照状态来分类

成品:完成实例化,完成初始化

半成品:完成实例化但未完成初始化

Q:当持有了某一个对象的引用之后,能否在后续步骤的时候给对象进行赋值操作?

A:可以,实例化和初始化可以分开执行。

构造器解决不了,创建对象必须赋值。

Map:A 的半成品,查询是否有B;B的半成品;B成品,A成品

Q:如何区分成品和半成品?

各级缓存的缓存结构?

A:三级缓存。

ConcurrentHashMap<String,Object> singletonObjects 一级缓存 256

ConcurrentHashMap<String,Object> earlySingletonObjects 二级缓存 16

HashMap<String,ObjectFactory<?>> singletonFactories 三级缓存 16

ObjectFactory:函数式接口,可以将lambda表达式作为参数放到方法实参中,在方法执行的时候,并不会实际调用当前lambda表达式,只有在调用getObject方法的时候才会去调用lambda表达式

三级缓存:

key:a

value:()->getEarlyBeanReference(beanName,mbd,bean)

key:b

value:()->getEarlyBeanReference(beanName,mbd,bean)

二级缓存:key:a value:A@1761半成品

存入二级缓存后,将三级缓存中的内容移除(因为永远是先查123顺序,3级缓存之后用不到)

一级缓存: 

key:b

value :B@2182 成品对象

key:a

value:B@2182成品

RuntimeBeanReference

getBean

doGetBean

createBean

doCreateBean 

createBeanInstance

populateBean

Q1:三个缓存结构map分別存储什么类型的对象

1:成品

2:半成品

3:lambda表达式

Q2:三个缓存结构map的查找顺序?

A:123

Q3:如果只有一个map结构,能解决循环依赖问题吗?

理论上可行,实际上每人这么干,使用2个map的意思在于将半成品和成品对象进行区分,半成本对象是不能直接暴露给外部对象使用的。

可行的话:设计复杂的map,将成品和半成品状态用标志位区分,但操作代码较麻烦,直接用2个map較方便

Q4:如果只有2个map结构,能解决循环依赖问题吗?

可以,但是有前提:没有代理对象的时候,当不使用aop的時候,2个缓存就可以解决循环依赖

Q5:为什么使用三级缓存之后,就可以解决带aop的循环引用?

5-1 一个容器中,能包含同名的2个对象吗? 不能

5-2 对象创建过程中,原始对象有没有可能需要生成代理对象?有可能

5-3 如果创建出了代理对象,那么程序在调用的时候到底使用原始对象还是代理对象?

应该用代理对象,但是程序是死的,是提前写好的,他怎么知道要选择代理对象呢?

所以当出现代理对象的时候,要使用代理对象替换掉原始对象

5-4 代理对象的创建是在初始化过程的扩展阶段,而属性的赋值是在生成代理对象之前执行的,那么怎么完成替换呢?

需要在属性赋值的时候判断是否需要生成代理对象

5-5 那为什么非要使用 lambda表达式的机制来完成呢?

对象在什么时候被暴露出去或者被其他对象引用是没办法提前确定好的,所以只有在被调用的那一刻才可以进行原始对象还是代理对象的判断,使用lambda表达式是一种回调机制,不暴露的时候不需要调用执行,当需要被调用的时候,才真正执行lambda表达式,来判断返回的到底是代理对象还是原始对象。

创建A

放3级缓存,放lambda表达式,因为a不知道什么时候被调用

给A赋值B

创建B对象

放3级缓存,放lambda表达式,因为b不知道什么时候被调用

给B赋值A

此时需要判断赋值的时候到底是原始对象还是代理对象,调用lambda表达式来确定返回的到底是什么对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值