我们假设一个场景 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会直接报错