bean加載一:轉換beanName、循環依賴、實例化

本文會介紹上文中提到的<1>,<2>,<3>這三個步驟的內容

1 transformedBeanName

  final String beanName = transformedBeanName(name);

這段代碼的作用主要有兩個:
1.如果傳入的bean name是別名,那么就要獲取對應的真實的bean name。也會存在循環別名即別名B指向別名A,別名A指向真實的bean name的情況。
2.去掉"&"符號,獲取真實的bean name。如:name從"&MyBean"變成"MyBean"。

protected String transformedBeanName(String name) {
    return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}

public static String transformedBeanName(String name) {
    Assert.notNull(name, "'name' must not be null");
    if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
        return name;
    }
    // 循環去掉前面所有的 & 符號
    return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
        do {
            beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
        }
        while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
        return beanName;
    });
}

public String canonicalName(String name) {
    String canonicalName = name;
    // Handle aliasing...
    String resolvedName;
    do {
        // 遞歸獲取別名對應的beanName
        resolvedName = this.aliasMap.get(canonicalName);
        if (resolvedName != null) {
            canonicalName = resolvedName;
        }
    }
    while (resolvedName != null);
    return canonicalName;
}

2 getSingleton

spring為了避免創建單例時出現循環依賴的問題,所以創建bean的時候不等bean創建完成就會創建bean的ObjectFactory提早曝光加入到緩存中,一旦下一個bean創建時需要依賴這個bean就直接使用ObjectFactory。

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    // 從單例緩存中加載 bean
    Object singletonObject = this.singletonObjects.get(beanName);
    // 緩存中的 bean 為空,且當前 bean 正在創建(注:第七步創建單例類型bean的時候會保存在一個緩存中)
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        synchronized (this.singletonObjects) {
            // 從 earlySingletonObjects 獲取,表示此bean正在創建,不進行后續處理
            singletonObject = this.earlySingletonObjects.get(beanName);
            // earlySingletonObjects 中沒有,且允許提前創建
            if (singletonObject == null && allowEarlyReference) {
                // 從 singletonFactories 中獲取對應的 ObjectFactory
                ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                if (singletonFactory != null) {
                    // 獲得 bean
                    // 對應第7步中的 getEarlyBeanReference(beanName, mbd, bean)
                    singletonObject = singletonFactory.getObject();
                    // 添加 bean 到 earlySingletonObjects 中
                    this.earlySingletonObjects.put(beanName, singletonObject);
                    // 從 singletonFactories 中移除對應的 ObjectFactory
                    this.singletonFactories.remove(beanName);
                }
            }
        }
    }
    return singletonObject;
}

最大的難點可能在于其中的好幾個map對象到底是什么意思,下面來簡單介紹下:
1.singletonObjects(一級緩存):保存beanName與bean實例之間的關系。
那么這個里面的數據來自哪里呢?答案在 bean 加載過程中的第7步

DefaultSingletonBeanRegistry#getSingleton(創建單例模式的java bean)
-> DefaultSingletonBeanRegistry#addSingleton方法

protected void addSingleton(String beanName, Object singletonObject) {
    synchronized (this.singletonObjects) {
        this.singletonObjects.put(beanName, singletonObject);
        this.singletonFactories.remove(beanName);
        this.earlySingletonObjects.remove(beanName);
        this.registeredSingletons.add(beanName);
    }
}

從二級和三級緩存中刪除,添加到一級緩存中
2.earlySingletonObjects(二級緩存):也是保存beanName與bean實例之間的關系,與singletonObjects不同的地方是,當bean還在創建過程中的時候就可以通過這個map拿到對應的bean實例,相當于保存的是半成品的bean,用來檢測循環引用。
3.singletonFactories(三級緩存):保存beanName與創建bean的工廠之間的關系。這個map中的數據來源于,bean 加載過程中的第7步

AbstractAutowireCapableBeanFactory#createBean
-> AbstractAutowireCapableBeanFactory#doCreateBean
-> DefaultSingletonBeanRegistry#addSingletonFactory

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);
        }
    }
}

從三級緩存中刪除,加入二級緩存。由此可以看到二級緩存和三級緩存其實是互斥的

總的三級緩存的使用邏輯大概是
在A的創建過程中會添加三級緩存,然后進行A的屬性填充,如果此時A依賴了B,那么需要首先創建B。當B的創建又需要用到A,就會從三級緩存中獲取,然后通過singletonFactory.getObject()獲取初始A對象(沒有初始化和填充屬性,但是經過了AOP代理),放入二級緩存并且刪除三級緩存,返回半成品的A作為B的屬性,然后B的創建就完成了。返回A的創建中,當A創建完成后,刪除二級和三級緩存,之后的A獲取都可以在一級緩存中拿到。
從這里可以看出來,就算是使用一級和二級緩存也能實現解決循環依賴的問題,那為什么還要使用三級緩存呢?原因主要是:二級緩存放入的是實例化后的半成品對象,如果這個對象還需要實現AOP功能,那么就需要使用ObjectFactory包裝然后放入三級緩存中。然后在第三步的getObjectForBeanInstance方法中,取出ObjectFactory包裝的AOP之后的對象。

3 getObjectForBeanInstance

protected Object getObjectForBeanInstance(
        Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

    // 若為工廠類引用(name 以 & 開頭)
    // Don't let calling code try to dereference the factory if the bean isn't a factory.
    if (BeanFactoryUtils.isFactoryDereference(name)) {
        if (beanInstance instanceof NullBean) {
            return beanInstance;
        }
        // 類型不為 FactoryBean
        if (!(beanInstance instanceof FactoryBean)) {
            throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
        }
    }

    // 到這里就有了一個 Bean 實例,當然該實例可能是會是一個正常的 bean 又或者是一個 FactoryBean
    // 如果是 FactoryBean 并且 name 中有 & 符號,則直接返回,否則使用 FactoryBean 創建bean
    // Now we have the bean instance, which may be a normal bean or a FactoryBean.
    // If it's a FactoryBean, we use it to create a bean instance, unless the
    // caller actually wants a reference to the factory.
    if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
        return beanInstance;
    }

    Object object = null;
    // 若 BeanDefinition 為 null,則從緩存中加載 Bean 對象
    if (mbd == null) {
        object = getCachedObjectForFactoryBean(beanName);
    }
    // 若 object 依然為空,則可以確認,beanInstance 一定是 FactoryBean 。從而,使用 FactoryBean 獲得 Bean 對象
    if (object == null) {
        // Return bean instance from factory.
        FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
        // Caches object obtained from FactoryBean if it is a singleton.
        // containsBeanDefinition 檢測 beanDefinitionMap 中也就是在所有已經加載的類中
        // 檢測所有已經加載的bean是否包含 beanName
        if (mbd == null && containsBeanDefinition(beanName)) {
            // 將存儲 XML 配置文件的 GenericBeanDefinition 轉換為 RootBeanDefinition,
            // 如果指定 BeanName 是子 Bean 的話同時會合并父類的相關屬性
            mbd = getMergedLocalBeanDefinition(beanName);
        }
        // 是否是用戶定義的,而不是應用程序本身定義的
        boolean synthetic = (mbd != null && mbd.isSynthetic());
        // 核心處理方法,使用 FactoryBean 獲得 Bean 對象
        object = getObjectFromFactoryBean(factory, beanName, !synthetic);
    }
    return object;
}

其中最核心的是getObjectFromFactoryBean,接下來看看這個方法。

protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
    // 為單例模式且緩存中存在
    if (factory.isSingleton() && containsSingleton(beanName)) {
        synchronized (getSingletonMutex()) {
            // 從緩存中獲取指定的 factoryBean
            Object object = this.factoryBeanObjectCache.get(beanName);
            if (object == null) {
                // 為空,則從 FactoryBean 中獲取對象
                object = doGetObjectFromFactoryBean(factory, beanName);
                // Only post-process and store if not put there already during getObject() call above
                // (e.g. because of circular reference processing triggered by custom getBean calls)
                Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
                if (alreadyThere != null) {
                    object = alreadyThere;
                }
                else {
                    // 需要后續處理
                    if (shouldPostProcess) {
                        // 若該 Bean 處于創建中,則返回非處理對象,而不是存儲它
                        if (isSingletonCurrentlyInCreation(beanName)) {
                            // Temporarily return non-post-processed object, not storing it yet..
                            return object;
                        }
                        // 單例 Bean 的前置處理
                        // 設置該bean正在創建過程中
                        beforeSingletonCreation(beanName);
                        try {
                            // 對從 FactoryBean 獲取的對象進行后處理
                            // 生成的對象將暴露給 bean 引用
                            object = postProcessObjectFromFactoryBean(object, beanName);
                        }
                        catch (Throwable ex) {
                            throw new BeanCreationException(beanName,
                                    "Post-processing of FactoryBean's singleton object failed", ex);
                        }
                        finally {
                            // 單例 Bean 的后置處理
                            // 移除該bean正在創建
                            afterSingletonCreation(beanName);
                        }
                    }
                    // 添加到 factoryBeanObjectCache 中,進行緩存
                    if (containsSingleton(beanName)) {
                        this.factoryBeanObjectCache.put(beanName, object);
                    }
                }
            }
            return object;
        }
    }
    else {
        // 為空,則從 FactoryBean 中獲取對象
        Object object = doGetObjectFromFactoryBean(factory, beanName);
        // 需要后續處理
        if (shouldPostProcess) {
            try {
                // 對從 FactoryBean 獲取的對象進行后處理
                // 生成的對象將暴露給 bean 引用
                object = postProcessObjectFromFactoryBean(object, beanName);
            }
            catch (Throwable ex) {
                throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
            }
        }
        return object;
    }
}

這里把這個代碼拆分成if和else看。

3.1 if塊代碼

當bean是單例的并且已經存在緩存中。獲取同步鎖,如果能夠獲取到對應的FactoryBean就直接返回,否則通過傳入的factory#getObject獲取對象并且進行后置處理。

3.1.1 doGetObjectFromFactoryBean

權限驗證以及通過 factory#getObject 方法獲取對象。

3.1.2 后置處理

3.1.2.1 beforeSingletonCreation

protected void beforeSingletonCreation(String beanName) {
        if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }
    }

校驗當前bean沒有在檢測并且設置正在創建

3.1.2.2 postProcessObjectFromFactoryBean

    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
            throws BeansException {

        Object result = existingBean;
        // 獲取 BeanPostProcessor 數組
        for (BeanPostProcessor processor : getBeanPostProcessors()) {
            // 循環調用 postProcessAfterInitialization 方法,如果為空立即返回
            Object current = processor.postProcessAfterInitialization(result, beanName);
            if (current == null) {
                return result;
            }
            result = current;
        }
        return result;
    }

BeanPostProcessor 也就是后置處理器,可用于類增強。后續專門介紹

3.1.2.3 afterSingletonCreation

校驗當前bean沒有在檢測并且移除正在創建

3.2 else

bean不是單例對象,直接通過 factory#getObject 方法獲取對象,并且進行后置處理。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。