Spring源碼閱讀----Spring IoC之finishBeanFactoryInitialization(續(xù))很重要的getBean

概述

前文中介紹的finishBeanFactoryInitialization方法是IOC的核心涂臣,其中的getBean方法還沒有講解到,在這里繼續(xù)展開解析。我們閱讀源碼時(shí)流炕,要抓主次,先按主線下來仅胞,然后在主線里做支路的標(biāo)記每辟,等主線閱讀完后,再回顧支路的標(biāo)記慢慢進(jìn)去展開干旧,這樣避免引起“"迷路現(xiàn)象"渠欺,在源碼中兜轉(zhuǎn)一回不明白所以然。
在前文中椎眯,我們主要關(guān)注的是finishBeanFactoryInitialization里的preInstantiateSingletons方法挠将,實(shí)例化所有剩余的非懶加載單例 bean,那如何實(shí)例化的呢编整?這得用到getBean這個(gè)方法舔稀。

getBean

AbstractBeanFactory類中的getBean方法,這里邊有好幾個(gè)getBean方法,我們主要看第一個(gè)用到的掌测,源碼如下:

    @Override
    public Object getBean(String name) throws BeansException {
        return doGetBean(name, null, null, false);
    }

doGetBean是主要做事的方法,那么多getBean方法只是給外部提供一個(gè)調(diào)用接口,查看doGetBean的源碼:

    /**
     * Return an instance, which may be shared or independent, of the specified bean.
     */
    @SuppressWarnings("unchecked")
    protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
            @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
        //注釋1. 獲取 bean 名稱内贮,如果需要,去掉引用前綴(例如修飾符)赏半,還有將別名轉(zhuǎn)換成最終 beanName
        final String beanName = transformedBeanName(name);
        Object bean;

        // Eagerly check singleton cache for manually registered singletons.
        // 注釋2. 檢查緩存中或者實(shí)例工廠是否有對(duì)應(yīng)的實(shí)例或者從 singletonFactories 中的 ObjectFactory 中獲取
        Object sharedInstance = getSingleton(beanName);

        // 注釋3. 如果緩存中存在該beanName的實(shí)例
        if (sharedInstance != null && args == null) {
            if (logger.isTraceEnabled()) {
                if (isSingletonCurrentlyInCreation(beanName)) {
                    logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
                            "' that is not fully initialized yet - a consequence of a circular reference");
                }
                else {
                    logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
                }
            }
            // 注釋3-1. 返回對(duì)應(yīng)的實(shí)例贺归,普通的bean返回
            // 對(duì) FactoryBean 的特殊處理,是返回指定方法返回的實(shí)例
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }
        else {
            // 注釋4. 如果緩存中不存在該beanName的實(shí)例  
            // Fail if we're already creating this bean instance:
            // We're assumably within a circular reference.
            // 注釋4-1. 循環(huán)依賴校驗(yàn),假設(shè)我們?cè)谝粋€(gè)循環(huán)引用中断箫,我們之前已經(jīng)創(chuàng)建了這個(gè)bean實(shí)例拂酣,則會(huì)拋出錯(cuò)誤:循環(huán)依賴
            if (isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }

            // Check if bean definition exists in this factory.
            // 注釋4-2. 獲取parentBeanFactory
            BeanFactory parentBeanFactory = getParentBeanFactory();

            // 注釋4-2-1. 如果parentBeanFactory存在衅斩,并且beanName在當(dāng)前BeanFactory不存在Bean定義光督,則嘗試從parentBeanFactory中獲取bean實(shí)例
            if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
                // Not found -> check parent.將別名解析成真正的beanName
                String nameToLookup = originalBeanName(name);

                //通過parentBeanFactory獲取bean實(shí)例
                if (parentBeanFactory instanceof AbstractBeanFactory) {
                    return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                            nameToLookup, requiredType, args, typeCheckOnly);
                }
                else if (args != null) {
                    // Delegation to parent with explicit args.
                    return (T) parentBeanFactory.getBean(nameToLookup, args);
                }
                else if (requiredType != null) {
                    // No args -> delegate to standard getBean method.
                    return parentBeanFactory.getBean(nameToLookup, requiredType);
                }
                else {
                    return (T) parentBeanFactory.getBean(nameToLookup);
                }
            }

            // 注釋4-2-2. 如果不是僅僅做類型檢查則是創(chuàng)建 bean,這里要將beanName放到alreadyCreated緩存
            if (!typeCheckOnly) {
                markBeanAsCreated(beanName);
            }

            try {
                // 注釋5. 根據(jù)beanName重新獲取MergedBeanDefinition
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);

                // 檢查MergedBeanDefinition
                checkMergedBeanDefinition(mbd, beanName, args);

                // Guarantee initialization of beans that the current bean depends on.
                // 注釋6. 保證當(dāng)前 bean 所依賴的bean的實(shí)例化,
                String[] dependsOn = mbd.getDependsOn();

                // 如果存在依賴則需要遞歸實(shí)例化依賴的 bean
                if (dependsOn != null) {
                    for (String dep : dependsOn) {

                        // 檢查循環(huán)依賴報(bào)錯(cuò)~
                        if (isDependent(beanName, dep)) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                        }
                        // 將dep和beanName的依賴關(guān)系注冊(cè)到緩存中
                        registerDependentBean(dep, beanName);
                        try {
                            // 獲取dep對(duì)應(yīng)的bean實(shí)例惋耙,如果dep還沒有創(chuàng)建bean實(shí)例,則創(chuàng)建dep的bean實(shí)例
                            getBean(dep);
                        }
                        catch (NoSuchBeanDefinitionException ex) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                        }
                    }
                }

                // Create bean instance. 創(chuàng)建 bean 實(shí)例
                // 注釋7. singleton 單例模式(最常使用)
                if (mbd.isSingleton()) {
                    // 注釋7-1.  scope為singleton的bean創(chuàng)建
                    //ObjectFactory為函數(shù)式接口,lambda表達(dá)式重寫了getObject方法
                    sharedInstance = getSingleton(beanName, () -> {
                        try {

                            //注釋7-1-1. 創(chuàng)建Bean實(shí)例
                            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;
                        }
                    });

                    //注釋7-1-2.返回beanName對(duì)應(yīng)的實(shí)例對(duì)象
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }
                //注釋7-2. scope為prototype的bean創(chuàng)建
                else if (mbd.isPrototype()) {
                    // It's a prototype -> create a new instance.
                    Object prototypeInstance = null;
                    try {

                        //注釋7-2-1. 創(chuàng)建實(shí)例前的操作
                        beforePrototypeCreation(beanName);

                        //注釋7-2-2.  創(chuàng)建Bean實(shí)例
                        prototypeInstance = createBean(beanName, mbd, args);
                    }
                    finally {
                        //注釋7-2-3.創(chuàng)建實(shí)例后的操作
                        afterPrototypeCreation(beanName);
                    }

                    //注釋7-2-4.返回beanName對(duì)應(yīng)的實(shí)例對(duì)象
                    bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                }
                //注釋7-3. 其他scope的bean創(chuàng)建
                else {
                    //注釋7-3-1. 獲取scopeName诱渤,根據(jù)scopeName蚌铜,從緩存拿到scope實(shí)例
                    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 {

                        //注釋7-3-2. 其他scope的bean創(chuàng)建,新建了一個(gè)ObjectFactory
                        //ObjectFactory為函數(shù)式接口,lambda表達(dá)式重寫了getObject方法
                        Object scopedInstance = scope.get(beanName, () -> {
                            //創(chuàng)建實(shí)例前的操作
                            beforePrototypeCreation(beanName);
                            try {
                                //創(chuàng)建bean實(shí)例
                                return createBean(beanName, mbd, args);
                            }
                            finally {
                                //創(chuàng)建實(shí)例后的操作
                                afterPrototypeCreation(beanName);
                            }
                        });
                        //返回beanName對(duì)應(yīng)的實(shí)例對(duì)象
                        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.
        // 檢查需要的類型是否符合 bean 的實(shí)際類型
        if (requiredType != null && !requiredType.isInstance(bean)) {
            try {
                //類型不對(duì),則嘗試轉(zhuǎn)換bean類型
                T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
                if (convertedBean == null) {
                    throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
                }
                return convertedBean;
            }
            catch (TypeMismatchException ex) {
                if (logger.isTraceEnabled()) {
                    logger.trace("Failed to convert bean '" + name + "' to required type '" +
                            ClassUtils.getQualifiedName(requiredType) + "'", ex);
                }
                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
            }
        }

        //返回創(chuàng)建出來的bean實(shí)例對(duì)象
        return (T) bean;
    }

跟著注釋走一遍饺谬,理解完其執(zhí)行過程后捂刺,進(jìn)入源碼解析。

注釋2.檢查緩存中或者實(shí)例工廠是否有對(duì)應(yīng)的實(shí)例或者從 singletonFactories 中的 ObjectFactory 中獲取募寨。在前文中對(duì)getSingleton這個(gè)方法解析過一次族展,里邊使用了三級(jí)緩存的概念,可以回顧一下拔鹰。
注釋3-1. 返回對(duì)應(yīng)的實(shí)例(見源碼解析1)
注釋4-2 通過parentBeanFactory 獲取bean實(shí)例
注釋4-2-2 判斷如果不是僅僅做類型檢查則是創(chuàng)建 bean仪缸,這里要將beanName放到alreadyCreated緩存(見源碼解析2)
注釋5. 獲取MergedBeanDefinition,參考前文中的getMergedLocalBeanDefinition方法解析
注釋6. 保證當(dāng)前 bean 所依賴的bean的實(shí)例化,isDependent方法來檢查循環(huán)依賴列肢,registerDependentBean方法為記錄beanName所對(duì)應(yīng)的bean和所依賴的ben(dep)之間的依賴關(guān)系恰画,注冊(cè)到緩存中。(見源碼解析3)
注釋7. 按scope不同進(jìn)行創(chuàng)建 bean 實(shí)例
注釋7-1. scope為singleton的bean創(chuàng)建,這里調(diào)用了getSingleton(String beanName, ObjectFactory<?> singletonFactory)方法(見源碼解析4)
注釋7-1-1. 創(chuàng)建Bean實(shí)例,createBean方法(這個(gè)方法很重要瓷马,在下一篇詳細(xì)解析)
注釋7-3-2 創(chuàng)建prototype的bean實(shí)例前的操作beforePrototypeCreation方法拴还、創(chuàng)建實(shí)例后的操作afterPrototypeCreation方法,可以點(diǎn)進(jìn)去跟蹤簡(jiǎn)單了解一下這個(gè)執(zhí)行過程:主要是在進(jìn)行 bean 實(shí)例的創(chuàng)建前,將 beanName 添加到 prototypesCurrentlyInCreation 緩存决采;bean 實(shí)例創(chuàng)建后自沧,將 beanName 從 prototypesCurrentlyInCreation 緩存中移除。這邊 prototypesCurrentlyInCreation 存放的類型為 Object树瞭,在只有一個(gè) beanName 的時(shí)候拇厢,直接存該 beanName,也就是 String 類型晒喷;當(dāng)有多個(gè) beanName 時(shí)孝偎,轉(zhuǎn)成 Set 來存放。

【源碼解析1】 獲取 beanName 對(duì)應(yīng)的實(shí)例對(duì)象:AbstractBeanFactory類中的getObjectForBeanInstance方法:

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

        // Don't let calling code try to dereference the factory if the bean isn't a factory.
        // 查看isFactoryDereference可知道凉敲,這里判斷的是 beanName 前綴是否是& 符號(hào)
        if (BeanFactoryUtils.isFactoryDereference(name)) {

            //如果是NullBean類型衣盾,直接返回
            if (beanInstance instanceof NullBean) {
                return beanInstance;
            }

            // 如果不是空 bean,又不是工廠 bean爷抓,報(bào)錯(cuò)
            if (!(beanInstance instanceof FactoryBean)) {
                throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
            }
        }

        // 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.

            // 如果beanInstance不是FactoryBean(也就是普通bean)势决,則直接返回beanInstance
            // 如果beanInstance是FactoryBean,并且name以“&”為前綴蓝撇,則直接返回beanInstance(以“&”為前綴代表想獲取的是FactoryBean本身)
        if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
            return beanInstance;
        }

        // 加載工廠 bean
        // 從上面排除信息可以知道果复,這里開始beanInstance是FactoryBean,但name不帶有“&”前綴渤昌,表示想要獲取的是FactoryBean創(chuàng)建的對(duì)象實(shí)例
        Object object = null;
        if (mbd == null) {
            // 如果mbd為空,先從緩存factoryBeanObjectCache中獲取
            object = getCachedObjectForFactoryBean(beanName);
        }

        if (object == null) {
            // Return bean instance from factory.
            // 到了這一步虽抄,很確定是工廠 bean 類型了,類型強(qiáng)轉(zhuǎn)
            FactoryBean<?> factory = (FactoryBean<?>) beanInstance;

            // Caches object obtained from FactoryBean if it is a singleton.
            // mbd為空走搁,但是該bean的BeanDefinition在緩存中存在,則獲取該bean的MergedBeanDefinitio
            if (mbd == null && containsBeanDefinition(beanName)) {
                mbd = getMergedLocalBeanDefinition(beanName);
            }

            // 判斷mbd 是否是合成的BeanDefinition
            boolean synthetic = (mbd != null && mbd.isSynthetic());

            //注釋1. 通過 getObjectFromFactoryBean方法獲取對(duì)象實(shí)例
            object = getObjectFromFactoryBean(factory, beanName, !synthetic);
        }
        return object;
    }

FactoryBean 前文中已經(jīng)介紹過其定義了迈窟,是一種特殊的bean即工廠 bean私植,可以自己創(chuàng)建 bean 實(shí)例。
這里主要繼續(xù)解析getObjectFromFactoryBean方法车酣,獲取對(duì)象實(shí)例(見源碼解析1-1)

【源碼解析1-1】 FactoryBeanRegistrySupport類中曲稼,從 FactoryBean 獲取對(duì)象實(shí)例:getObjectFromFactoryBean

protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {

        //factoryBean如果是單例,并且已經(jīng)存在于單例對(duì)象緩存中
        if (factory.isSingleton() && containsSingleton(beanName)) {

            //加鎖操作
            synchronized (getSingletonMutex()) {

                //獲取緩存
                Object object = this.factoryBeanObjectCache.get(beanName);
                if (object == null) {

                    // 注釋1. 緩存不存在,通過factoryBean獲取beanName實(shí)例對(duì)象
                    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) {

                        //如果該beanName已經(jīng)在緩存中存在骇径,則將object替換成緩存中的alreadyThere
                        object = alreadyThere;
                    }
                    else {
                        if (shouldPostProcess) {

                            //該beanName被標(biāo)記了屬于正在創(chuàng)建的bean躯肌,存在于Set singletonsCurrentlyInCreation中
                            //則直接返回該實(shí)例對(duì)象
                            if (isSingletonCurrentlyInCreation(beanName)) {
                                // Temporarily return non-post-processed object, not storing it yet..
                                return object;
                            }
                            // 創(chuàng)建單例前的前置操作,校驗(yàn)下存不存在者春,不存在拋異常
                            beforeSingletonCreation(beanName);

                            try {
                                //注釋2. 對(duì)bean實(shí)例進(jìn)行后置處理破衔,執(zhí)行所有已注冊(cè)的BeanPostProcessor的postProcessAfterInitialization方法
                                object = postProcessObjectFromFactoryBean(object, beanName);
                            }
                            catch (Throwable ex) {
                                throw new BeanCreationException(beanName,
                                        "Post-processing of FactoryBean's singleton object failed", ex);
                            }
                            finally {
                                // 創(chuàng)建單例后的后置操作,校驗(yàn)下存不存在钱烟,不存在拋異常
                                afterSingletonCreation(beanName);
                            }
                        }
                        if (containsSingleton(beanName)) {
                            this.factoryBeanObjectCache.put(beanName, object);
                        }
                    }
                }
                return object;
            }
        }
        else {
            //factoryBean不是單例的情況下晰筛,通過factoryBean獲取beanName實(shí)例對(duì)象
            Object object = doGetObjectFromFactoryBean(factory, beanName);
            if (shouldPostProcess) {
                try {
                    // 對(duì)bean實(shí)例進(jìn)行后置處理,執(zhí)行所有已注冊(cè)的BeanPostProcessor的postProcessAfterInitialization方法
                    object = postProcessObjectFromFactoryBean(object, beanName);
                }
                catch (Throwable ex) {
                    throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
                }
            }
            //返回object實(shí)例對(duì)象
            return object;
        }
    }

這個(gè)方法執(zhí)行流程看下來拴袭,真正做事的得看doGetObjectFromFactoryBean這個(gè)方法读第。
注釋1. 緩存不存在,通過factoryBean獲取beanName實(shí)例對(duì)象,doGetObjectFromFactoryBean(見源碼解析1-2)
注釋2. 對(duì)bean實(shí)例進(jìn)行后置處理,執(zhí)行所有已注冊(cè)的BeanPostProcessor的postProcessAfterInitialization方法,postProcessObjectFromFactoryBean(見源碼解析1-3)

【源碼解析1-2】 通過FactoryBean來獲取到對(duì)象實(shí)例 : doGetObjectFromFactoryBean

private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
            throws BeanCreationException {

        Object object;
        try {
            //系統(tǒng)安全管理驗(yàn)證
            if (System.getSecurityManager() != null) {
                AccessControlContext acc = getAccessControlContext();
                try {
                    //調(diào)用FactoryBean的getObject方法獲取bean對(duì)象實(shí)例
                    object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
                }
                catch (PrivilegedActionException pae) {
                    throw pae.getException();
                }
            }
            else {
                //不作系統(tǒng)安全管理驗(yàn)證拥刻,調(diào)用FactoryBean的getObject方法獲取bean對(duì)象實(shí)例
                object = factory.getObject();
            }
        }
        catch (FactoryBeanNotInitializedException ex) {
            throw new BeanCurrentlyInCreationException(beanName, ex.toString());
        }
        catch (Throwable ex) {
            throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
        }

        // Do not accept a null value for a FactoryBean that's not fully
        // initialized yet: Many FactoryBeans just return null then.
        if (object == null) {
            if (isSingletonCurrentlyInCreation(beanName)) {
                //getObject返回的是空值怜瞒,并且該beanName正在初始化中,則直接拋異常
                throw new BeanCurrentlyInCreationException(
                        beanName, "FactoryBean which is currently in creation returned null from getObject");
            }
            //創(chuàng)建一個(gè)新的NullBean對(duì)象
            object = new NullBean();
        }
            //返回創(chuàng)建好的bean對(duì)象實(shí)例
        return object;
    }

這里主要就是通過factory bean 的 getObject方法來獲取對(duì)象般哼。

【源碼解析1-3】 子類AbstractAutowireCapableBeanFactory postProcessObjectFromFactoryBean吴汪,重寫了父類FactoryBeanRegistrySupport里的方法:

    @Override
    protected Object postProcessObjectFromFactoryBean(Object object, String beanName) {
              //
        return applyBeanPostProcessorsAfterInitialization(object, beanName);
    }

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

        Object result = existingBean;

        //遍歷所有注冊(cè)的BeanPostProcessor實(shí)現(xiàn)類,調(diào)用postProcessAfterInitialization方法
        for (BeanPostProcessor processor : getBeanPostProcessors()) {

            //在bean初始化后蒸眠,調(diào)用postProcessAfterInitialization方法
            Object current = processor.postProcessAfterInitialization(result, beanName);
            if (current == null) {
                //如果返回null漾橙,則直接返回結(jié)果
                return result;
            }
            //有值則直接返回
            result = current;
        }
        return result;
    }

我們創(chuàng)建的beanFactory為DefaultListableBeanFactory類型,這邊走的是 AbstractAutowireCapableBeanFactory 里的方法楞卡,它為DefaultListableBeanFactory父類霜运,F(xiàn)actoryBeanRegistrySupport的子類,@Override重寫父類FactoryBeanRegistrySupport的postProcessObjectFromFactoryBean方法蒋腮。
前面的registerBeanPostProcessors已經(jīng)幫我們注冊(cè)了各類BeanPostProcessors淘捡,它會(huì)再bean實(shí)例化后,初始化階段執(zhí)行被執(zhí)行其接口的方法池摧。

【源碼解析2】 將beanName放到alreadyCreated緩存 : markBeanAsCreated方法

    protected void markBeanAsCreated(String beanName) {
        if (!this.alreadyCreated.contains(beanName)) {
            synchronized (this.mergedBeanDefinitions) {
                //如果alreadyCreated緩存中不包含beanName
                if (!this.alreadyCreated.contains(beanName)) {
                    // Let the bean definition get re-merged now that we're actually creating
                    // the bean... just in case some of its metadata changed in the meantime.
                    //將beanName的MergedBeanDefinition從mergedBeanDefinitions緩存中移除焦除,在之后重新獲取MergedBeanDefinition
                    clearMergedBeanDefinition(beanName);
                    //將beanName添加到alreadyCreated緩存中,代表該beanName的bean實(shí)例已經(jīng)創(chuàng)建(或即將創(chuàng)建)
                    this.alreadyCreated.add(beanName);
                }
            }
        }
    }

alreadyCreated 是一個(gè)Set集合作為已經(jīng)創(chuàng)建(或即將創(chuàng)建)的實(shí)例集合险绘,
這邊會(huì)將 beanName 對(duì)應(yīng)的 MergedBeanDefinition 移除踢京,然后在之后的代碼重新獲取誉碴,主要是為了使用最新的 MergedBeanDefinition 來進(jìn)行創(chuàng)建操作。

【源碼解析3】 保證當(dāng)前 bean 所依賴的bean的實(shí)例化
檢查循環(huán)依賴:來自DefaultSingletonBeanRegistry類中的 isDependent方法

    protected boolean isDependent(String beanName, String dependentBeanName) {
        synchronized (this.dependentBeanMap) {
            return isDependent(beanName, dependentBeanName, null);
        }
    }

    private boolean isDependent(String beanName, String dependentBeanName, @Nullable Set<String> alreadySeen) {

        if (alreadySeen != null && alreadySeen.contains(beanName)) {
            return false;
        }
        // 點(diǎn)開canonicalName方法可以看到將別名解析為真正的名稱
        String canonicalName = canonicalName(beanName);

        //依賴canonicalName的beanName集合
        Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
        if (dependentBeans == null) {
            //如果dependentBeans為空瓣距,則兩者必然還未確定依賴關(guān)系黔帕,返回fals
            return false;
        }
        if (dependentBeans.contains(dependentBeanName)) {
            //如果dependentBeans包含dependentBeanName,則表示兩者已確定依賴關(guān)系蹈丸,返回true
            return true;
        }

        //循環(huán)檢查成黄,即檢查依賴canonicalName的所有beanName是否存在被dependentBeanName依賴的(即隔層依賴)
        for (String transitiveDependency : dependentBeans) {
            if (alreadySeen == null) {
                alreadySeen = new HashSet<>();
            }

            //已經(jīng)檢查過的添加到alreadySeen,避免重復(fù)檢查
            alreadySeen.add(beanName);

            //隔層依賴檢查
            if (isDependent(transitiveDependency, dependentBeanName, alreadySeen)) {
                return true;
            }
        }
        return false;
    }

registerDependentBean方法:記錄beanName所對(duì)應(yīng)的bean和所依賴的ben(dep)之間的依賴關(guān)系逻杖,注冊(cè)到緩存中

    public void registerDependentBean(String beanName, String dependentBeanName) {
        //解析別名
        String canonicalName = canonicalName(beanName);

        //加鎖操作
        synchronized (this.dependentBeanMap) {
            //如果依賴關(guān)系還沒有注冊(cè)奋岁,則將兩者的關(guān)系注冊(cè)到dependentBeanMap和dependenciesForBeanMap緩存
            Set<String> dependentBeans =
                    this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8));
            if (!dependentBeans.add(dependentBeanName)) {
                return;
            }
        }

        //加鎖操作
        synchronized (this.dependenciesForBeanMap) {
            //將canonicalName添加到dependentBeanName依賴的beanName集合中
            Set<String> dependenciesForBean =
                    this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8));
            dependenciesForBean.add(canonicalName);
        }
    }

dependenciesForBeanMap:beanName 對(duì)應(yīng)的 bean 依賴的所有 bean 的 beanName 集合,
前面提到的dependentBeanMap 是所有依賴 beanName 對(duì)應(yīng)的 bean 的 beanName 集合

【源碼解析4】 前文介紹過getSingleton(String beanName)方法荸百,這里調(diào)用的是 DefaultSingletonBeanRegistry類中的getSingleton(String beanName, ObjectFactory<?> singletonFactory)方法

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
        Assert.notNull(beanName, "Bean name must not be null");
        // 注釋 全局變量闻伶,加鎖
        synchronized (this.singletonObjects) {
            // 首先檢查beanName對(duì)應(yīng)的bean實(shí)例是否在緩存中存在
            Object singletonObject = this.singletonObjects.get(beanName);

            //如果不存在,則進(jìn)入創(chuàng)建操作
            if (singletonObject == null) {
                //當(dāng)bean factory的單例處于destruction狀態(tài)時(shí),不允許進(jìn)行單例bean創(chuàng)建够话,拋出異常
                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!)");
                }

                if (logger.isDebugEnabled()) {
                    logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
                }

                // 注釋1-1. 創(chuàng)建單例前的操作蓝翰,校驗(yàn)是否 beanName 是否有別的線程在初始化,并加入初始化狀態(tài)中
                beforeSingletonCreation(beanName);
                boolean newSingleton = false;
                boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
                if (recordSuppressedExceptions) {
                    this.suppressedExceptions = new LinkedHashSet<>();
                }
                try {
                    // 執(zhí)行singletonFactory的getObject方法獲取bean實(shí)例
                    //實(shí)際執(zhí)行的是 createBean 方法
                    singletonObject = singletonFactory.getObject();

                    //標(biāo)記為新的單例對(duì)象
                    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;
                    }
                    //注釋1-2.  創(chuàng)建單例后的操作女嘲,移除初始化狀態(tài)
                    afterSingletonCreation(beanName);
                }
                if (newSingleton) {
                    // 注釋2. 如果是新的單例對(duì)象,加入緩存
                    //singletonObjects畜份、registeredSingletons
                    addSingleton(beanName, singletonObject);
                }
            }

            // 返回單例對(duì)象
            return singletonObject;
        }
    }

這個(gè)方法傳入的第二個(gè)參數(shù)為lambda表達(dá)式的匿名函數(shù),ObjectFactory為函數(shù)式接口,所以singletonFactory的getObject方法會(huì)觸發(fā)匿名函數(shù)里的createBean方法欣尼。
注釋1-1爆雹、1-2. 創(chuàng)建單例前的操作、創(chuàng)建單例后的操作愕鼓,出現(xiàn)在創(chuàng)建單例的前后(見源碼解析5)
注釋2. 如果是新的單例對(duì)象钙态,將 beanName 和對(duì)應(yīng)的單例對(duì)象添加到緩存中:addSingleton方法

protected void addSingleton(String beanName, Object singletonObject) {
    synchronized (this.singletonObjects) {
        // 1.添加到單例對(duì)象緩存
        this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));
        // 2.將單例工廠緩存移除(已經(jīng)不需要)
        this.singletonFactories.remove(beanName);
        // 3.將早期單例對(duì)象緩存移除(已經(jīng)不需要)
        this.earlySingletonObjects.remove(beanName);
        // 4.添加到已經(jīng)注冊(cè)的單例對(duì)象緩存
        this.registeredSingletons.add(beanName);
    }
}

這個(gè)方法是比較重要的,多關(guān)注一下拒啰,乍一看就是對(duì)各類Map的操作驯绎,前文我們已經(jīng)了解過singletonObjects、earlySingletonObjects谋旦、singletonFactories 構(gòu)成了三級(jí)緩存的概念剩失,這里是把創(chuàng)建好的實(shí)例對(duì)象移動(dòng)到一級(jí)緩存singletonObjects 和注冊(cè)的單例對(duì)象緩存registeredSingletons中,移除掉二級(jí)册着、三級(jí)緩存拴孤。一級(jí)緩存中的是完全態(tài)創(chuàng)建的實(shí)例對(duì)象,二級(jí)甲捏、三級(jí)是創(chuàng)建中的半成品實(shí)例對(duì)象演熟。

【源碼解析5】

protected void beforeSingletonCreation(String beanName) {
    // 先校驗(yàn)beanName是否為要在創(chuàng)建檢查排除掉的(inCreationCheckExclusions緩存),如果不是,
    // 則將beanName加入到正在創(chuàng)建bean的緩存中(Set)芒粹,如果beanName已經(jīng)存在于該緩存兄纺,會(huì)返回false拋出異常(這種情況出現(xiàn)在構(gòu)造器的循環(huán)依賴)
    if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
        throw new BeanCurrentlyInCreationException(beanName);
    }
}
 
protected void afterSingletonCreation(String beanName) {
    // 先校驗(yàn)beanName是否為要在創(chuàng)建檢查排除掉的(inCreationCheckExclusions緩存),如果不是化漆,
    // 則將beanName從正在創(chuàng)建bean的緩存中(Set)移除估脆,如果beanName不存在于該緩存,會(huì)返回false拋出異常
    if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
        throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
    }

inCreationCheckExclusions 是要在創(chuàng)建檢查排除掉的 beanName 集合座云,正常為空疙赠,可以不管。這邊主要是引入了 singletonsCurrentlyInCreation 緩存:當(dāng)前正在創(chuàng)建的 bean 的 beanName 集合朦拖。在 beforeSingletonCreation 方法中圃阳,通過添加 beanName 到該緩存,可以預(yù)防出現(xiàn)構(gòu)造器循環(huán)依賴的情況璧帝。

為什么這里無法解決構(gòu)造器循環(huán)依賴捍岳?

我們之前在前文提過,getSingleton 方法是解決循環(huán)引用的核心代碼裸弦。有一句話:“我們先用構(gòu)造函數(shù)創(chuàng)建一個(gè) “不完整” 的 bean 實(shí)例”祟同,從這句話可以看出,構(gòu)造器循環(huán)依賴是無法解決的理疙,因?yàn)楫?dāng)構(gòu)造器出現(xiàn)循環(huán)依賴,我們連 “不完整” 的 bean 實(shí)例都構(gòu)建不出來泞坦。Spring 能解決這類循環(huán)依賴的方案有:通過 setter 注入的循環(huán)依賴窖贤、通過屬性注入的循環(huán)依賴,使用@lazy注解,使用@PostConstruct等贰锁,優(yōu)先建議使用setter注入來解決赃梧。

總結(jié)

這里介紹了bean實(shí)例化部分的getBean方法,包括先從緩存中獲取實(shí)例(getSingleton)豌熄、 FactoryBean 的 bean 創(chuàng)建(getObjectForBeanInstance)授嘀、實(shí)例化自己的依賴即dependOn變量(遞歸調(diào)用getBean來創(chuàng)建實(shí)例)、創(chuàng)建 bean 實(shí)例(createBean)锣险,以及創(chuàng)建前后一些標(biāo)記等蹄皱,createBean方法也是個(gè)很重要的方法,下一文中詳細(xì)介紹它芯肤。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末巷折,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子崖咨,更是在濱河造成了極大的恐慌锻拘,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,544評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件击蹲,死亡現(xiàn)場(chǎng)離奇詭異署拟,居然都是意外死亡婉宰,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門推穷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來芍阎,“玉大人,你說我怎么就攤上這事缨恒∏聪蹋” “怎么了?”我有些...
    開封第一講書人閱讀 162,764評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵骗露,是天一觀的道長(zhǎng)岭佳。 經(jīng)常有香客問我,道長(zhǎng)萧锉,這世上最難降的妖魔是什么珊随? 我笑而不...
    開封第一講書人閱讀 58,193評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮柿隙,結(jié)果婚禮上叶洞,老公的妹妹穿的比我還像新娘。我一直安慰自己禀崖,他們只是感情好衩辟,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著波附,像睡著了一般艺晴。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上掸屡,一...
    開封第一講書人閱讀 51,182評(píng)論 1 299
  • 那天封寞,我揣著相機(jī)與錄音,去河邊找鬼仅财。 笑死狈究,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的盏求。 我是一名探鬼主播抖锥,決...
    沈念sama閱讀 40,063評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼风喇!你這毒婦竟也來了宁改?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,917評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤魂莫,失蹤者是張志新(化名)和其女友劉穎还蹲,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,329評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡谜喊,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評(píng)論 2 332
  • 正文 我和宋清朗相戀三年潭兽,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片斗遏。...
    茶點(diǎn)故事閱讀 39,722評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡山卦,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出诵次,到底是詐尸還是另有隱情账蓉,我是刑警寧澤,帶...
    沈念sama閱讀 35,425評(píng)論 5 343
  • 正文 年R本政府宣布逾一,位于F島的核電站铸本,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏遵堵。R本人自食惡果不足惜箱玷,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評(píng)論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望陌宿。 院中可真熱鬧锡足,春花似錦、人聲如沸壳坪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽弥虐。三九已至扩灯,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間霜瘪,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工惧磺, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留颖对,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,729評(píng)論 2 368
  • 正文 我出身青樓磨隘,卻偏偏與公主長(zhǎng)得像缤底,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子番捂,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評(píng)論 2 353