Spring 通过三级缓存机制来解决循环依赖:
-
一级缓存:存放完全初始化好的单例 Bean。
-
二级缓存:存放正在创建但未完全初始化的 Bean 实例。
-
三级缓存:存放 Bean 工厂对象,用于提前暴露 Bean。
试问:三级缓存解决循环依赖的过程是什么样的? -
实例化 Bean 时,将其早期引用放入三级缓存。
-
其他依赖该 Bean 的对象,可以从缓存中获取其引用。
-
初始化完成后,将 Bean 移入一级缓存。
假如 A、B 两个类发生循环依赖:
A 实例的初始化过程:
①、创建 A 实例,实例化的时候把 A 的对象⼯⼚放⼊三级缓存,表示 A 开始实例化了,虽然这个对象还不完整,但是先曝光出来让大家知道。
②、A 注⼊属性时,发现依赖 B,此时 B 还没有被创建出来,所以去实例化 B。
③、同样,B 注⼊属性时发现依赖 A,它就从缓存里找 A 对象。依次从⼀级到三级缓存查询 A。
发现可以从三级缓存中通过对象⼯⼚拿到 A,虽然 A 不太完善,但是存在,就把 A 放⼊⼆级缓存,同时删除三级缓存中的 A,此时,B 已经实例化并且初始化完成了,把 B 放入⼀级缓存。
④、接着 A 继续属性赋值,顺利从⼀级缓存拿到实例化且初始化完成的 B 对象,A 对象创建也完成,删除⼆级缓存中的 A,同时把 A 放⼊⼀级缓存
⑤、最后,⼀级缓存中保存着实例化、初始化都完成的 A、B 对象。