20--Spring實(shí)例化單例bean的準(zhǔn)備工作

上一節(jié)分析了Spring從緩存中獲取單例bean的過程,相對(duì)于創(chuàng)建一個(gè)全新的單例bean,該過程還是很簡(jiǎn)單的,本節(jié)接著分析創(chuàng)建單例bean的準(zhǔn)備工作。

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly)
            throws BeansException {

    // 1、轉(zhuǎn)換bean的名稱,去掉&前綴,且如果bean有別名的話,優(yōu)先使用別名
    final String beanName = transformedBeanName(name);
    Object bean;

    // 2、從緩存中獲取bean
    Object sharedInstance = getSingleton(beanName);
    if (sharedInstance != null && args == null) {
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }

    // 3、如果未能從緩存中獲取到bean,則要重新創(chuàng)建bean
    else {
        // Fail if we're already creating this bean instance: We're assumably within a circular reference.
        // 3.1判斷指定的原型模式的bean是否當(dāng)前正在創(chuàng)建(在當(dāng)前線程內(nèi)),如果是->則拋出異常(Spring不會(huì)解決原型模式bean的循環(huán)依賴)
        if (isPrototypeCurrentlyInCreation(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }

        // Check if bean definition exists in this factory.
        // 3.2 檢測(cè)bean definition是否存在beanFactory中
        BeanFactory parentBeanFactory = getParentBeanFactory();
        // 如果當(dāng)前BeanFactory中不包含給定beanName的beanDefinition定義,且父beanFactory不為空,則去父beanFactory中再次查找
        if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
            // 3.3 將name轉(zhuǎn)換為原始beanName
            //     因?yàn)檫@里的name已經(jīng)經(jīng)過beanName的規(guī)范處理,例如:&myBean-->規(guī)范-->myBean
            //     所以當(dāng)我們?cè)俅稳ジ竍eanFactory查找時(shí),要將beanName再次轉(zhuǎn)換為原始的beanName,myBean-->回轉(zhuǎn)-->&myBean
            String nameToLookup = originalBeanName(name);
            // 3.4 下面會(huì)遞歸調(diào)用各種getBean的方法重載,從當(dāng)前bean的父factoryBean中加載bean
            if (parentBeanFactory instanceof AbstractBeanFactory) {
                return ((AbstractBeanFactory) parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
            }
            else if (args != null) {
                // 參數(shù)不為空,則委托parentBeanFactory使用顯式參數(shù)調(diào)動(dòng)
                return (T) parentBeanFactory.getBean(nameToLookup, args);
            }
            else if (requiredType != null) {
                // 參數(shù)為空,則委托parentBeanFactory使用標(biāo)準(zhǔn)的getBean方法獲取bean
                return parentBeanFactory.getBean(nameToLookup, requiredType);
            }
            else {
                // 否則委托parentBeanFactory使用默認(rèn)的getBean方法
                return (T) parentBeanFactory.getBean(nameToLookup);
            }
        }

        // 3.3 如果當(dāng)前bean不是用于類型檢查,則將該bean標(biāo)記為已經(jīng)被創(chuàng)建或者即將被創(chuàng)建
        if (!typeCheckOnly) {
            markBeanAsCreated(beanName);
        }

        try {
            // 3.4 合并beanDefinition,如果指定的bean是一個(gè)子bean的話,則遍歷其所有的父bean
            final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
            // 校驗(yàn)合并的beanDefinition,如果驗(yàn)證失敗,則拋出異常
            checkMergedBeanDefinition(mbd, beanName, args);

            // 3.5 確保初始化當(dāng)前bean所依賴的bean。
            String[] dependsOn = mbd.getDependsOn();
            if (dependsOn != null) {
                // 循環(huán)所有的依賴bean,并遞歸實(shí)例化
                for (String dep : dependsOn) {
                    if (isDependent(beanName, dep)) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                    }
                    // 注冊(cè)依賴
                    registerDependentBean(dep, beanName);
                    try {
                        // 實(shí)例化依賴的bean
                        getBean(dep);
                    }
                    catch (NoSuchBeanDefinitionException ex) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                    }
                }
            }

            // 3.6 創(chuàng)建單例bean
            if (mbd.isSingleton()) {
                sharedInstance = getSingleton(beanName, () -> {
                    try {
                        // 創(chuàng)建bean
                        return createBean(beanName, mbd, args);
                    }
                    catch (BeansException ex) {
                        // Explicitly remove instance from singleton cache: It might have been put there
                        // eagerly by the creation process, to allow for circular reference resolution.
                        // Also remove any beans that received a temporary reference to the bean.
                        destroySingleton(beanName);
                        throw ex;
                    }
                });
                bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
            }

            // 創(chuàng)建原型模式bean
            else if (mbd.isPrototype()) {
                // It's a prototype -> create a new instance.
                Object prototypeInstance = null;
                try {
                    beforePrototypeCreation(beanName);
                    prototypeInstance = createBean(beanName, mbd, args);
                }
                finally {
                    afterPrototypeCreation(beanName);
                }
                bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
            }

            else {
                String scopeName = mbd.getScope();
                final Scope scope = this.scopes.get(scopeName);
                if (scope == null) {
                    throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
                }
                try {
                    Object scopedInstance = scope.get(beanName, () -> {
                        beforePrototypeCreation(beanName);
                        try {
                            return createBean(beanName, mbd, args);
                        }
                        finally {
                            afterPrototypeCreation(beanName);
                        }
                    });
                    bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                }
                catch (IllegalStateException ex) {
                    throw new BeanCreationException(beanName,
                            "Scope '" + scopeName + "' is not active for the current thread; consider " +
                            "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
                            ex);
                }
            }
        }
        catch (BeansException ex) {
            cleanupAfterBeanCreationFailure(beanName);
            throw ex;
        }
    }

    // Check if required type matches the type of the actual bean instance.
    if (requiredType != null && !requiredType.isInstance(bean)) {
        try {
            T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
            if (convertedBean == null) {
                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
            }
            return convertedBean;
        }
        catch (TypeMismatchException ex) {
            throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
        }
    }
    return (T) bean;
}

在到達(dá)步驟3.6之前的工作,都是為創(chuàng)建當(dāng)前單例bean的準(zhǔn)備工作。其中包括了:對(duì)BeanDefinition的檢測(cè)、如果當(dāng)前BeanFactory中不包含BeanDefinition則對(duì)父BeanFactory的檢測(cè)、BeanDefinition的合并、依賴bean的初始化等等工作。

1.創(chuàng)建單例bean
// 3.6 創(chuàng)建單例bean
if (mbd.isSingleton()) {
    sharedInstance = getSingleton(beanName, () -> {
        try {
            // 創(chuàng)建bean
            return createBean(beanName, mbd, args);
        }
        catch (BeansException ex) {
            // Explicitly remove instance from singleton cache: It might have been put there
            // eagerly by the creation process, to allow for circular reference resolution.
            // Also remove any beans that received a temporary reference to the bean.
            destroySingleton(beanName);
            throw ex;
        }
    });
    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
  • getSingleton方法分析
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    synchronized (this.singletonObjects) {
        // 1、嘗試從緩存中獲取bean
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null) {
            if (this.singletonsCurrentlyInDestruction) {
                throw new BeanCreationNotAllowedException(beanName,
                        "Singleton bean creation not allowed while singletons of this factory are in destruction " +
                        "(Do not request a bean from a BeanFactory in a destroy method implementation!)");
            }
            // 2、創(chuàng)建bean之前的回調(diào)方法
            beforeSingletonCreation(beanName);
            boolean newSingleton = false;
            boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
            if (recordSuppressedExceptions) {
                this.suppressedExceptions = new LinkedHashSet<>();
            }
            try {
                // 3、通過getObject創(chuàng)建bean的實(shí)例
                singletonObject = singletonFactory.getObject();
                newSingleton = true;
            }
            catch (IllegalStateException ex) {
                // Has the singleton object implicitly appeared in the meantime ->
                // if yes, proceed with it since the exception indicates that state.
                singletonObject = this.singletonObjects.get(beanName);
                if (singletonObject == null) {
                    throw ex;
                }
            }
            catch (BeanCreationException ex) {
                if (recordSuppressedExceptions) {
                    for (Exception suppressedException : this.suppressedExceptions) {
                        ex.addRelatedCause(suppressedException);
                    }
                }
                throw ex;
            }
            finally {
                if (recordSuppressedExceptions) {
                    this.suppressedExceptions = null;
                }
                // 4、創(chuàng)建bean之后的回調(diào)方法
                afterSingletonCreation(beanName);
            }
            if (newSingleton) {
                // 5、將新創(chuàng)建的單例bean加入緩存
                addSingleton(beanName, singletonObject);
            }
        }
        return singletonObject;
    }
}

該方法中完成了對(duì)單例bean的創(chuàng)建工作,并在創(chuàng)建bean之前和之后進(jìn)行方法回調(diào)進(jìn)行一些異常信息的檢查,最后將單例bean加入緩存中。其中關(guān)鍵的步驟就是第三步
通過getObject創(chuàng)建bean的實(shí)例,singletonObject = singletonFactory.getObject();,這里初學(xué)者閱讀起來可能稍微有些繞,singletonFactory.getObject();方法執(zhí)行后會(huì)回到3.6中的return createBean(beanName, mbd, args);完成對(duì)bean的創(chuàng)建。

  • createBean方法分析
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {

    RootBeanDefinition mbdToUse = mbd;

    // Make sure bean class is actually resolved at this point, and
    // clone the bean definition in case of a dynamically resolved Class
    // which cannot be stored in the shared merged bean definition.
    // 確保此時(shí)bean類已經(jīng)被解析,并且在動(dòng)態(tài)解析類不能存儲(chǔ)在共享合并bean定義中時(shí)克隆bean定義。
    Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
    if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
        mbdToUse = new RootBeanDefinition(mbd);
        mbdToUse.setBeanClass(resolvedClass);
    }

    // 準(zhǔn)備和驗(yàn)證配置的方法注入
    // 注意:這里處理的是replace-method和lookup-method方法注入,而不是@Override注解
    try {
        mbdToUse.prepareMethodOverrides();
    }
    catch (BeanDefinitionValidationException ex) {
        throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),beanName, "Validation of method overrides failed", ex);
    }

    try {
        // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
        // 讓beanPostprocessor有機(jī)會(huì)返回一個(gè)代理而不是目標(biāo)bean實(shí)例。
        Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
        if (bean != null) {
            return bean;
        }
    }
    catch (Throwable ex) {
        throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "beanPostProcessor before instantiation of bean failed", ex);
    }

    try {
        // 執(zhí)行bean創(chuàng)建,并返回bean的實(shí)例
        Object beanInstance = doCreateBean(beanName, mbdToUse, args);
        return beanInstance;
    }
    catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
        throw ex;
    }
    catch (Throwable ex) {
        throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
    }
}

從方法名上好像已經(jīng)接觸到了IoC的核心-->bean的創(chuàng)建,但是很遺憾,該方法中依然只是例行檢查工作,真正的創(chuàng)建方法在doCreateBean中,從這里也能看出spring代碼閱讀的一個(gè)小技巧,真正干活兒的往往是doXXX開頭的方法,而在doXXX之前都是做一些準(zhǔn)備工作。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容