spring如何解决循环依赖

我们假设一个场景 ServiceA 、 ServiceB

class ServiceA{
    @Autowired
    ServiceB serviceB;
}

class ServiceB{
      @Autowired
    ServiceA serviceA;
}

在getBean()的时候 serviceA 需要依赖serviceB,而serviceB又依赖serviceA
spring底层提供了三级缓存机制来解决spring的循环依赖

spring源码

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
/** Names of beans that are currently in creation. 正在创建的单例bean*/
private final Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<>(16));

//一级缓存 存放实例化且装配完成的bean
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
//二级缓存 存放实例化但还未装配完成的bean
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
//三级缓存 key:beanName value:lambna表达式 可以用BeanFactory.getObject()方法获取原始对象协助早期暴露的bean完成aop 。引入三级缓存的目的是为了解决如果serviceA和serviceB被aop增强的场景
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
..............
}

spring解决循环依赖的过程:
step1:serviceA创建bean实例,标记BeanA为创建中放入singletonsCurrentlyInCreation 。发现需要注入serviceB的实例,此时serviceB还没有实例完成,spring会把半成品serviceA放入到二级缓存中(即早期暴露的单例对象缓存池)
step2:serviceB创建bean实例发现需要注入serviceA实例(此时的serviceA是个半成品),serviceB找到serviceA并把它注入到自己对象中,B的bean实例创建完成,serviceB的bean实例被放入一级缓存池。
step3:serviceA去一级缓存池找到了beanB ,把beanB注入到自己的bean实例中,此时BeanA创建完成,BeanA被放入一级缓存池,删除二级缓存池中早期暴露的BeanA。
注意 spring只有在单例模型下且set注入的场景才能解决循环依赖,也就是说原型模型和构造注入的场景无法解决循环依赖 ,spring会直接报错

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容