场景分析
public class AService {
@Autowired
private BService BService;
public AService(){
System.out.println("init aService");
}
}
public class BService {
@Autowired
private AService aService;
public BService(){
System.out.println("init bService");
}
}
类似于上述代码,在Aservice中依赖BService属性,在BService中依赖Aservice的情况称之为循环依赖。
在spring Bean的生命周期中,当Bean实例化之后,还存在了属性填充,生命周期初始回调,完成aop代理等等阶段。
在初始化AService时,在属性填充节点需要BService对象,但是此时spring容器中不存在BService对象,需要去创建BService。
创建BService的过程中完成了Bean实例化,在属性填充时又需要Aservice对象,但是此时AService还处于属性填充阶段,没有完全初始化好,此时如果Aservice不需要完成aop代理,那么只需要将正在初始化的Aservice对象引用赋给BService中Aservice的属性就好了,当时如果Aservice需要进行aop代理或者其他的一些操作呢?这个问题就是循环依赖的问题。
需要解决循环依赖的问题,就需要了解下spring三级缓存
spring三级缓存
/** Cache of singleton objects: bean name to bean instance. */
//单例对象缓存池,经过完整的spring bean的生命周期的单例Bean对象,在spring容器初始化的放入
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/** Cache of singleton factories: bean name to ObjectFactory. */
//实例化单例对象的ObjectFactory缓存池,可以获取提前aop之后的对象
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
/** Cache of early singleton objects: bean name to bean instance. */
//早期单例对象缓存池,提前aop之后的对象,没有经过完成的spring bean生命周期
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
三级缓存的使用:
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
获取单例对象时,先从一级缓存(singletonObjects)中获取,一级缓存(singletonObjects)获取不到并且获取的bean在当前正在创建的bean集合中时再从三级级缓存(earlySingletonObjects)中获取,三级缓存(earlySingletonObjects)获取不到时,获取二级缓存(singletonFactories)中的ObjectFactory对象并调用ObjectFactory对象的getObject()方法获取提前aop的对象,并放入三级缓存(earlySingletonObjects)中方便下次获取。
spring中循环依赖解决原理
首先需要解决循环依赖,相互依赖的Bean必须是单例的,并且是通过属性注入的。
spring使用了三级缓存来解决循环依赖,当创建一个单例Bean时,spring会将当前创建Bean的名称放入一个集合中,表示该bean处于创建过程中。
//当前正在创建的bean名称集合
private final Set<String> singletonsCurrentlyInCreation =
Collections.newSetFromMap(new ConcurrentHashMap<>(16));
//当前在创建检查中被排除在外的bean的名称
private final Set<String> inCreationCheckExclusions =
Collections.newSetFromMap(new ConcurrentHashMap<>(16));
protected void beforeSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}
在实例化bean之后,判断bean是否单例&&是否允许循环依赖&&是否正在创建中,如果是则将生成对应的ObjectFactory对象添加到二级缓存中,该ObjectFactory对象获取获取到提前aop的bean对象。
当有别bean需要此正在创建中的bean时,可以调用ObjectFactory对象的getObject()方法获取提前aop的对象。
这里的“提前aop”可能不太准确,还执行了别的实现了SmartInstantiationAwareBeanPostProcessor接口的Bean后置处理完成除aop以外的事。以下方式是ObjectFactory对象的getObject()方法完成的事:
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
}
关闭循环依赖
AnnotationConfigApplicationContext ann = new AnnotationConfigApplicationContext();
ann.setAllowCircularReferences(false);//关闭循环依赖
ann.register(AppConfig.class);