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

Spring框架通过使用三级缓存来解决单例作用域的Bean的循环依赖问题。这三级缓存包括:

  1. 一级缓存(Singleton Objects Cache):这是Spring容器用来存储已经完全初始化的Bean的地方,也就是我们通常所说的Spring容器。

  2. 二级缓存(Early Singleton Objects Cache):这个缓存存储的是早期暴露的对象,也就是已经实例化但还未进行属性填充和初始化的对象(即完成构造器注入,但未完成setter注入和初始化方法执行)。

  3. 三级缓存(Singleton Factories Cache):这个缓存存储的是Bean工厂对象,用于解决循环依赖。

当Spring创建bean时,它首先查看一级缓存。如果在一级缓存中找不到该bean,那么Spring就会尝试去创建这个bean。在创建bean的过程中,Spring首先将创建的bean实例(尚未初始化)放入三级缓存,然后进行属性填充,如果在填充过程中发现该bean依赖于另一个bean,那么Spring就会尝试创建这个依赖的bean。

如果这个依赖的bean又依赖于刚才正在创建的bean,那么由于刚才正在创建的bean已经在三级缓存中,所以Spring可以从三级缓存中获取到这个bean的引用,从而解决了循环依赖的问题。

当bean完全创建完成后,Spring会将这个bean从三级缓存移动到二级缓存,然后最终移动到一级缓存,并从二级和三级缓存中删除这个bean。

需要注意的是,这种解决循环依赖的方式只适用于单例作用域的bean,且只能解决构造器之外的其他方法(如setter方法)引起的循环依赖。对于构造器引起的循环依赖,Spring无法解决,会抛出BeanCurrentlyInCreationException异常。对于prototype作用域的bean,Spring也无法解决其循环依赖,会抛出BeanCurrentlyInCreationException异常。

发表评论

后才能评论