循环依赖:指多个bean之间相互依赖从而形成一个闭环。
即A依赖B,B依赖C,C依赖A这种。
?Spring中出现循环依赖的情况:
构造器注入:无法解决
多列setter注入:无法解决
单列setter注入:可通过三成缓存解决
Spring通过三层缓存解决依赖
三层缓存:
singletonObject:一级缓存,存放完成初始化的对象,可以直接使用 earlySingletonObject:二级缓存,存放早期对象的引用,尚未装配属性的对象 singletonFactories:三级缓存,存放完成实例化的对象工厂
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
...
// 从上至下 分表代表这“三级缓存”
//一级缓存
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);
初始化步骤:
- createBeanInstance:实例化,即调用对象的构造方法实例化对象
- populateBean:填充属性,主要对 bean 的依赖属性注入(@Autowired)
- initializeBean:回到一些如initMethod,InitalizingBean等方法
过程简单介绍一下:
在有循环依赖的的时候,a对象初始化的流程中,将b对象也实例化和初始化了,在b的初始化过程中,将a从三级缓存移到了二级缓存中,当b初始化完成后继续向下执行,会执行到addSingleton()
protected void addSingleton(String beanName, Object singletonObject) {
synchronized(this.singletonObjects) {
// 将b加入到1级缓存
this.singletonObjects.put(beanName, singletonObject);
// 将b从三级缓存中删除
this.singletonFactories.remove(beanName);
// 将b从二级缓存中删除(b在二级缓存中没有,即空删除)
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
在b的所用工作做完之后,返回到a初始化属性b的代码,调用doCreateBean方法继续执行,最终也会到addSingleton()方法,将a也加入一级缓存,并且从二级缓存中删除a。这样a和b两个循环依赖的bean都被放入到一级缓存中。
系统启动获取配置文件后,程序是依次读取并加载的,所以当执行配置文件时,先获取a对象,如果获取不到则实例化a对象,然后初始化a对象即给a添加b属性,在添加b属性的时候先获取b,如果b存在则直接给a设置,不存在则实例化b,并且初始化b对象即给b添加对应的属性。
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 先从一级缓存中获取a对象的实例
Object singletonObject = this.singletonObjects.get(beanName);
// 如果从一级缓存中获取不到a对象,那么检查该对象是否正在被创建,如果正在被创建,则进入if循环中
if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
synchronized(this.singletonObjects) {
// 从二级缓存中获取该对象
singletonObject = this.earlySingletonObjects.get(beanName);
// 如果二级缓存中无法获取该对象,那么一定会进入如下if方法,因为allowEarlyReference传过来的时候就是true
if (singletonObject == null && allowEarlyReference) {
// 从三级缓存中获取该对象
ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// 如果获取到了该对象,就将三级缓存中的对象放到二级缓存中,并且将三级缓存中的对象删除
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
|