Spring源碼解析(四)循環依賴
本次的重點是註明循環依賴的關鍵方法,和方法邏輯
假設有如下情況:
<bean id="beanA" class="BeanA" p:beanB-ref="beaB"/>
<bean id="beanB" class="BeanB" p:beanA-ref="beaA"/>
beanA和beanB之間相互引用
這裏會涉及到在spring內部所使用的兩個內部屬性,singletonFactories和earlySingletonObjects,這兩個屬性在類DefaultSingletonBeanRegistry中被定義,定義如下:
/** Cache of singleton factories: bean name --> ObjectFactory */
private final Map<String, ObjectFactory> singletonFactories = new HashMap<String, ObjectFactory>();
/** Cache of early singleton objects: bean name --> bean instance */
private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>();
官方對此的屬性定義不是很明確,這裏我們可以這樣來理解。
- singletonFactories,用於存儲在spring內部所使用的beanName->對象工廠的引用,一旦最終對象被創建(通過objectFactory.getObject()),此引用信息將刪除
- earlySingletonObjects,用於存儲在創建Bean早期對創建的原始bean的一個引用,注意這裏是原始bean,即使用工廠方法或構造方法創建出來的對象,一旦對象最終創建好,此引用信息將刪除
從上面的解釋,可以看出,這兩個對象都是一個臨時工。在所有的對象創建完畢之後,此兩個對象的size都爲0。
那麼再來看下這兩個對象如何進行協作:
方法1:
/**
* Add the given singleton factory for building the specified singleton
* if necessary.
* <p>To be called for eager registration of singletons, e.g. to be able to
* resolve circular references.
* @param beanName the name of the bean
* @param singletonFactory the factory for the singleton object
*/
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);
}
}
}
方法2:
/**
* Return the (raw) singleton object registered under the given name.
* <p>Checks already instantiated singletons and also allows for an early
* reference to a currently created singleton (resolving a circular reference).
* @param beanName the name of the bean to look for
* @param allowEarlyReference whether early references should be created or not
* @return the registered singleton object, or <code>null</code> if none found
*/
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
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);
}
方法3:
/**
* Add the given singleton object to the singleton cache of this factory.
* <p>To be called for eager registration of singletons.
* @param beanName the name of the bean
* @param singletonObject the singleton object
*/
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}