关于Spring的三级缓存
文章目录
前言
spring的循环依赖,互相持有引用,使得依赖注入的问题。
一、循环依赖
循环依赖是指循环引用,两个或多个Bean之间的互相引用。
1.相互依赖
两个Bean之间互相引用
class A{
@Autowird
private B b;
}
class B{
@Autowird
private A a;
}
2.三者间依赖
class A{
@Autowird
private B b;
}
class B{
@Autowird
private C c;
}
class C{
@Autowird
private A a;
}
3.自我依赖
class A{
@Autowird
private A a;
}
spring中的依赖注入机制,在启动时会自动给对应的Bean进行赋值,此时就会出现问题。
如1中的相互依赖,在对A进行实例化时,需要对其中的B进行赋值,若此时B未实例化,则对B进行实例化,然而B中又含有A,就会产生互相注入,却都无法成功,因此产生死循环,spring容器则无法启动。
二、缓存
1.一级缓存
使用缓存,不论bean中是否赋值,统一将实例化后的bean放入Ioc容器中,等bean全部实例化完成后,在扫描Ioc容器,对未进行赋值的bean进行二次赋值。
2.二级缓存
二级缓存是为了预防某些突发情况,假设只有一个缓存Ioc容器,在容器中存在多个bean,其中拥有已经赋值成功的bean和未赋值的bean,在此时若认为调用bean,调用到了未赋值的bean,可能会产生空指针异常。
因此另设置一层缓存,一级缓存存储已经实例化并成功赋值的bean,二级缓存则存储实例化但未赋值的bean
ps:抛开一些特殊情况,理论上循环依赖在此时可以认为解决
3.三级缓存
在spring使用中注入的bean也存在需要创建代理的bean,而代理的bean并不是在实例化之后就立马创建代理bean,而是要等到bean初始化完成之后才会去创建代理bean(粗略理解为二级缓存的临时bean赋值完后,才能去创建代理bean)
因此则需要第三层缓存去存储代理bean,否则注入原始bean就会产生错误,而代理bean的每个配置规则又不相同,三级缓存中存储的是创建代理bean的factory
总结
循环依赖单纯使用二级缓存就可以解决,而代理依赖则需要三级缓存。