Spring源碼解析(四)循環依賴

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);
        }
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章