springboot需要手动开启三级缓存吗_二级缓存

如图所示,假如有两个类A,B。A里面引用B,B里面引用A,此时出现循环依赖

分别有三个Map集合代表三级缓存

singletonFactories(三级缓存)

earlySingletonObjects(二级缓存)

单例池(singletonObjects)(一级缓存)

首先要创建A,并将A的信息存入createingSet中,此时实例化A生成一个A的普通对象,并将其存入三级缓存,三级缓存的value存入的则是一个lambda表达式。

表达式里面有三个参数,分别是beanName(bean的名字),mbd(beanDefinition),bean(普通对象)。lambda是用来提前进行Aop的,之所以存这三个参数是因为,在进行aop时是需要有一个普通对象的。

然后开始填充b属性,先去单例池中寻找是否存在B的对象,如果不存在,在去createingSet寻找B,判断是否出现循环依赖,不存在则是实例化一个B的普通对象,将生成B普通对象存入三级缓存,填充a属性时也是先去单例池中寻找,找不到再去createingSet中寻找,发现此时有A,则是出现了循环依赖,然后再去earlySingletonObjects(二级缓存)中寻找A对象,如果没有,则再去singletonFactories(三级缓存)中寻找,此时存在A对象,则将A对象拿出来,并执行lambda表达式判断是否需要进行aop,如果需要则初始化A的代理对象存入earlySingletonObjects(二级缓存)中,如果不需要则初始化一个普通对象存入earlySingletonObjects(二级缓存)中,然后填充B中的A属性,再填充A中的B属性。此时发现两个缓存就可以了

之所以需要三个缓存,是因为防止此时再有一个C对象与A同样发生循环依赖,那么C也会生成一个A的代理对象,那么B、C中的A属性就不是同一个对象,但A又是单例的,则此时就会出问题。

如果有另一个缓存来存之前出现循环依赖而生成的代理对象那么就可以直接从缓存中拿到前面生成的A代理对象,那么此时B、C拿到的就是A的同一个代理对象