2020年7月15日 作者 zeroheart

Spring的循环依赖和处理

先说结论:构造器和原型循环依赖,无法处理 ,setter注入和单例@Autowired注入可以处理。

原因:解决循环依赖,使用的是bean的中间态,需要在实例化(构造器执行之后)才能拿到这个中间对象。


创建一个bean,doCreateBean方法,分为createBeanInstance,populateBean和 initalizeBrann,单例和属性注入的循环依赖出现在populateBean,是可以处理的。

三级缓存

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); // 三级缓存

//正在创建的bean,创建完成时会将其移出
private final Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<>(16));

先从一级缓存singletonObjects中去获取。(如果获取到就直接return)

如果获取不到或者对象正在创建中(isSingletonCurrentlyInCreation()),那就再从二级缓存earlySingletonObjects中获取。(如果获取到就直接return)

如果还是获取不到,且允许singletonFactories(allowEarlyReference=true)通过getObject()获取。就从三级缓存singletonFactory.getObject()获取。(如果获取到了就从singletonFactories中移除,并且放进earlySingletonObjects。其实也就是从三级缓存移动(是剪切、不是复制哦~)到了二级缓存)

加入singletonFactories三级缓存的前提是执行了构造器就是在createBeanInstance方法之后执行,所以构造器的循环依赖没法解决

如果三级缓存获取不到,那就创建,然后进入singletonFactories,进入earlySingletonObjects,进入singletonObjects,得到bean。

参考: https://www.cnblogs.com/longy2012/articles/12834762.html