spring循環(huán)依賴的解決方案
Spring IOC循環(huán)依賴解決方案分析
這里Spring主要用了三層緩存來完成對(duì)循環(huán)依賴的實(shí)現(xiàn)。
下面的屬性來源于DefaultSingletonBeanRegistry類
/** Cache of singleton objects: bean name --> bean instance */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(64);
/** Cache of singleton factories: bean name --> ObjectFactory */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);
/** Cache of early singleton objects: bean name --> bean instance */
private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);
當(dāng)獲取一個(gè)實(shí)例對(duì)象的時(shí)候春贸,會(huì)調(diào)用此方法
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 != NULL_OBJECT ? singletonObject : null);
}
先從singletonObjects 找脖旱,如果找不到會(huì)從earlySingletonObjects中查詢讲竿,再找不到去singletonFactories 中去查詢掌猛,如果找到的話會(huì)放在earlySingletonObjects中凉驻,那么問題來了,singletonFactories的對(duì)象是什么時(shí)候放進(jìn)去的柒竞。
研究Spring構(gòu)造類實(shí)例的時(shí)候,通過AbstractAutowireCapableBeanFactory的doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)方法中調(diào)用addSingletonFactory方法將A類曝光到singletonFactories中播聪。
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized (this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
Spring注入一個(gè)類的大體步驟分為兩部分朽基,一是先完成對(duì)類的構(gòu)造工作,二是會(huì)對(duì)類的屬性進(jìn)行設(shè)置和填充
那么關(guān)于的單例的類實(shí)例之間的互相引用的問題就清晰了
假設(shè)A對(duì)象有個(gè)屬性B 則在A初始化的時(shí)候离陶,構(gòu)造完成之后就放在了singletonFactories中稼虎,當(dāng)發(fā)現(xiàn)去set屬性的時(shí)候發(fā)現(xiàn)B沒有初始化,于是接著初始化B招刨,設(shè)置屬性的時(shí)候在緩存中都可以拿到各自對(duì)象的引用霎俩,所以不會(huì)有循環(huán)依賴的報(bào)錯(cuò)