1.循环依赖的产生
在spring中对象默认都是单例的 ,意味整个容器中只有一个该类的对象。
如图,B类有一个属性a,A类有一个属性b。当B类创建对象时,要给a属性赋值;当A类创建对象时,要给b属性赋值,从而产生循环依赖。只要打破当前的闭环,循环依赖就不存在了。
循环依赖产生的根本就是属性赋值。
属性复值的方式有两种:
2.循环依赖的解决
打破当前的闭环,使用三级缓存(三个map集合)解决
半成品: 完成实例化但未完成初始化
成品:完整对象
3.三级缓存问题解析
//源码中的三个的map结构 ,对应的三级缓存
/\*\* Cache of singleton objects: bean name --> bean instance \*/
//一级缓存,用于保护BeanName和创建bean实例之间的关系
private final Map
/\*\* Cache of singleton factories: bean name --> ObjectFactory \*/
//三级缓存,用于保护beanName和创建bean的工厂之间的关系
private final Map
/\*\* Cache of early singleton objects: bean name --> bean instance \*/
//二级缓存,保护beanName和bean实例之间的关系,与singletonFactories的不同之处在于
//当一个单例bean被放到这里之后,那么当bean还在创建过程中就可以通过getbean方法获取到,可以方便进行循环依赖的检测
private final Map
3.1三级缓存中分别保存的是什么对象
1:成品对象
2:半成品对象
3:lambda表达式
3.2如果只使用1级缓存行不行?
不行,因为成品和半成品对象会放到起,在进行对象获取的时候有可能获取到半成品对象,这样的对象是没法使用的
3.3如果只有二级缓存行不行?
getSingleton
doCreateBean
只有二级缓存的时候也可以解决循环依赖的问题,
添加aop的实现之后,报错,This means that said other beans do not use the final version of the bean.没有使用最终版本的bean对象
3.4 三级缓存存在到底做了什么事?
如果一个对象需要被代理,生成代理对象,那么这个对象需要预先生成非代理对象吗? 需要
lambda getEarlyBeanReference().只要搞清楚这个方法的具体执行逻辑即可
在当前方法中,有可能会用代理对象替换非代理对象,如果没有三级缓存的话,那么就无法得到代理对象,换句话说
在整个容器中,包含了同名对象的代理对象和非代理对象,你觉得可以吗?
容器中,对象都是单例的,意味着根据名称只能获取一个对象的值, 此时同时存在两个对象的话,使用的时候应该取哪一个? 无法判断
谁也无法确认什么时候会调用当前对象,是在其他对象的执行过程中来进行调用的,而不是人为指定的,所以必须要保证容器中任何时候都只一
个对象供外部调用,所以在三级缓存中,完整了一件代理对象替换非代理对象的工作, 确定返回的是唯一的对象
三级缓存是为了解决在aop代理过程中产生的循环依赖问题,如果没有aop的话,二级缓存足矣解决循环依赖问题
手机扫一扫
移动阅读更方便
你可能感兴趣的文章