spring三级缓存解决aop代理循环依赖图示
spring三级缓存解决aop代理循环依赖图示
三级缓存
- 每一级缓存就是一个Map,就是存放的<beanName,对象>。spring容器的完整
getBean
流程是一级缓存----->二级缓存----->三级缓存----->都没有就创建----->doCreateBean
- 一级缓存
singletonObjects
: 已经创建完成可以直接使用的单例对象。通常说的spring容器,就是说的这个,创建完成的对象需要一个map存储。 - 二级缓存
earlySingletonObjects
: 早期对象,还在创建过程中的对象,可能是代理对象,也可能就是普通对象。 - 三级缓存
singletonFactories
: 用于生成代理对象获取返回自身的对象工厂。
正常生命周期
- 两个Bean相互依赖,并且不需要Aop代理。这种正常的生命周期,是可以通过二级缓存来解决循环依赖的。核心思想是:
通过二级缓存提前曝光未创建完成的Bean
。 - 然后属性填充时从二级缓存
earlySingletonObjects
中获取,然后赋值,是可以解决普通循环依赖的。 - 但是如果是需要产生代理对象的循环依赖是解决不了的。
首先来看普通循环依赖的结构:a和b相互依赖。
使用二级缓存【singletonObjects , earlySingletonObjects
】来解决的流程是这样的:
Aop代理循环依赖问题
- 先看一下aop循环依赖最终的结构应该是怎么样的。
- 如果是还是用刚刚的二级缓存来解决代理循环依赖问题,是有问题的,看图:
三级缓存解决Aop循环依赖
-
可以看出代理对象的循环依赖核心是需要填充属性时,应该填充的是代理对象,而不是之前的源对象。也就是说:
填充属性时,如果是需要代理,应该aop提前创建代理
-
流程如下图:
-
刚刚已经说了如果用一级缓存和二级缓存组合是不能解决有aop的循环依赖的,那如果是使用
一级缓存 singletonObjects + 三级缓存 singletonFactories
可以解决循环依赖吗? -
我觉得是不可以的。从上面的流程可以看到,最终是需要将源A对象替换为代理A对象的,而这是从
二级缓存
中获取的。也就是提前创建的代理对象A需要有存储中间的容器,二级缓存就是这个中间容器。 -
当然也可以直接把代理对象A存放到一级缓存
singletonObjects
中,但是此时对象A还在创建过程中,还没有填充属性,然后又另外的线程从容器中获取对象A,就会拿到这个还未创建完成的代理A对象。 -
而且直接将创建过程中的代理A对象存放入一级缓存
singletonObjects
,我觉得是不符合spring的设计理念的,一级缓存singletonObjects
的定义就是存放已经创建完成可以直接使用的单例对象。
总结
- 二级缓存可以解决没有aop的循环依赖。核心思路是
使用二级缓存来提前曝光创建过程中的对象
。 - 使用二级缓存来解决aop循环依赖的问题是:bean对象
属性填充的应该是代理对象
,而不是源对象。 - 三级缓存解决aop循环依赖核心思路:
打破bean的生命周期,属性赋值时aop提前创建代理对象
。 - 如果文章对你有帮助,可以
点赞+收藏+关注
支持一下