内容来自《Java Web 程序员面试笔试宝典》

【出现频率】★★★☆☆ 【学习难度】★★★☆☆

答案:循环依赖是对象之间的一种依赖关系,当两个或两个以上的bean对象互相持有对方的引用,最终形成一个相互依赖的闭环时,就叫循环依赖。

Spring容器会将每一个正在创建的Bean标识符放在一个“当前创建Bean池”中,在创建过程中Bean标识符将一直在池中存在。因此如果在创建Bean的过程中发现自己已经在“当前创建Bean池”中时,说明发生循环依赖,Spring容器将抛出BeanCurrentlyInCreationException异常。当Bean创建完成后,Bean标识符将从“当前创建Bean池”中清除掉。

Spring的构造注入无法解决循环依赖,因为依赖的对象始终在创建过程中。

Spring的Scope为singleton的setter注入在有循环依赖时不会发生问题,Spring通过三级缓存机制来解决这个问题。简单地说就是在Spring容器创建Bean时,当调用Bean的构造器完成对象初始化时,(但没有属性注入的bean实例对象,即没有完全实例化的对象,放到缓存中),通过缓存来提前暴露。这样就可以在进行属性注入时获得依赖对象的引用。@Autowired注解自动装配同此原理。

Spring的Scope为prototype的setter注入也无法解决循环依赖,因为设置为prototype作用域的Bean,Spring容器不进行缓存,因此无法提前暴露一个创建中的Bean。