Spring循环依赖解决
无法解决的循环依赖的方式
1) Spring无法解决构造方法注入引起的循环依赖问题
2) Spring无法解决多例对象的循环依赖问题,因为多例对象是不进行缓存的
循环依赖解决原理----三级缓存
//第一级缓存:缓存已经完成了实例化和属性设置的单例对象(单例对象缓存)
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
//第二级缓存:缓存完成了只完成实例化,没有设置依赖属性的单例对象(早期暴露的单例对象缓存)
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
//第三级缓存:缓存单例对象的对象工厂引用,工厂封装了生成对象的逻辑(单例对象工厂缓存)
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
解决步骤
doGetBean方法执行{
//1.分别从三级缓存获取对象,第三级缓存命中会提升到缓存到二级
Object sharedInstance = getSingleton(beanName);
//2.以下方法调用会先触发createBean方法创建Bean
sharedInstance = getSingleton(beanName, () -> createBean(beanName, mbd, args)
//3. createBean调用 doCreateBean
//4.然后doCreateBean调用addSingletonFactory方法将创建的Bean封装在工厂引用中,放入三级缓存中
//5.doCreateBean继续执行调用 populateBean方法设置属性,属性依赖Bean会触发继续调用doGetBean方法创建Bean,直到循环依赖的Bean被创建完,设置好依赖属性
//6.结束doCreateBean后继续步骤2方法执行会调用addSingleton将Bean缓存到第一级缓存,清除二三级缓存
doCreateBean调用addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
然后执行populateBean(beanName, mbd, instanceWrapper)设置属性,如果有依赖的Bean没有创建会触发doGetBean方法去创建依赖的Bean
}
相关方法
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//从一级缓存中获取实例: 一级缓存用于缓存已经完成实例化的单例Bean
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
//从二级缓存中获取: 二级缓存用于缓存已经实例化的Bean,但是还没有设置依赖的类
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
//从三级缓存获取:三级缓存用于缓存单例工厂,工厂封装了对应的创建Bean的方法
ObjectFactory<?> singletonFactory =
this.singletonFactories.get(beanName);
if (singletonFactory != null) {
//从工厂中获取单例
singletonObject = singletonFactory.getObject();
//放入二级缓存中
this.earlySingletonObjects.put(beanName, singletonObject);
//从三级缓存移除
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized (this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
//将刚刚创建的Bean封装到ObjectFactory中,保存到三级缓存
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
//Map缓存生成的单例名称与实例的映射
this.singletonObjects.put(beanName, singletonObject);
//移除缓存单例工厂,工厂是一个lamda表达式,可创建对应的实例对象
this.singletonFactories.remove(beanName);
//循环依赖时候暂时缓存未赋值完成的单例类,这里创建完成后移除缓存
this.earlySingletonObjects.remove(beanName);
//LinkedHashSet缓存已经注册了的单例Bean名称,用于检测重复注册的名字
this.registeredSingletons.add(beanName);
}
}