分别用一二三级缓存解决循环依赖的方案

Posted 技术无产者

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了分别用一二三级缓存解决循环依赖的方案相关的知识,希望对你有一定的参考价值。

一. 一级缓存

1.不考虑aop 使用—级缓存解决循环依赖

1>创建A对象,放到缓存中,这时候为A对象注入属性

   2>创建B放到缓存,从缓存中获得A对象,将B对象返回给A对象(这时候如果不考虑aop 一级缓存就可以解决循环依赖的问题了)
 

2.考虑aop时,一级缓存无法解决循环依赖的问题

         因为初始化操作必须放在aop代理之前, 否则导致初始化的时候无法改变代理对象的属性值( 具体见动态代理对象属性注入的文章 动态代理对象的属性注入_zyz的博客-CSDN博客),假设A和B对象互相引用,且A和B对象都使用aop进行了增强,则按照上面的逻辑,A对象放到缓存后,需要注入B对象,而缓存中没有B对象,则需要去创建B对象,这时候B对象可以从缓存中获得A对象,而B对象拿到的是没有进行aop增强的A对象,这时候就算把初始化B对象和为B对象生成aop代理的业务逻辑放在这,也只能保证A对象获得的是aop代理过的B对象,而B对象中的A对象是没有经过aop增强的,且经过jdk/cglib动态代理后对象的属性值是没有办法改变的,这时候为A生成aop增强过的对象也无法替换B对象中的A对象,所以一级缓存无法解决。

二.二级缓存

     二级缓存可以解决循环依赖,并且也可以解决循环依赖中的依赖对象被aop代理问题,只需要在三级循环的代码中

      就是普通对象初始化完成后,然后走到 getSingleton方法通过三级缓存创建对象, 假设A和B循环依赖,并且A和B都通过aop增强,假设先创建A,则当为A中注入B时,发现 B没有,就会去创建B,如果使用二级缓存,这时候直接通过对象工厂创建A的aop对象 ,放在一级缓存中,相当于A对象创建好了,这时候创建好B对象后,返回继续创建A对 象,这时候按顺序,A的属性注入后该进行初始化A对象了,但这时候在创建B时已经把 A对象放到一级缓存中了,这时候如果另一个线程来获取就会获得还没有完全初始化的 A对象(框架是单线程加载的,当框架加载好所有对象都创建好了,因该不会出现不安 全发布的情况),这时候也就会出现违背Spring创建对象的原则,即在对象没有完全初 始化的时候就出现在了一级缓存中,Spring创建对象的原则是在对象被完全初始化后才能被放到缓存中,被外界获取。

以上是关于分别用一二三级缓存解决循环依赖的方案的主要内容,如果未能解决你的问题,请参考以下文章

Spring三级缓存解决循环依赖问题

Spring是如何解决循环依赖的?

Spring使用三级缓存解决循环依赖的过程

Spring源码--02--三级缓存 解决 循环依赖

#yyds干货盘点# Spring源码三千问为什么要用三级缓存来解决循环依赖问题?二级缓存行不行?一级缓存行不行?

Spring循环依赖是如何解决的?