Spring源碼解析(七)-獲取單例bean

Spring版本

5.2.5.RELEASE

參考

Spring IOC 容器源碼分析 - 獲取單例 bean

源碼解析

1. BeanFactory#getBean(String name)

應(yīng)用初始化容器的時(shí)候,bean并不會(huì)馬上被加載(除非顯式指定lazyinit = false),而是在調(diào)用getBean的時(shí)候才會(huì)被加載沮尿,下面我們就來看看getBean的具體實(shí)現(xiàn)

getBean方法實(shí)際上是交由doGetBean實(shí)現(xiàn)的:

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

查看doGetBean方法:

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

        // 已注冊的bean會(huì)以<beanName,bean>的形式緩存在一個(gè)map
        // 1穴豫、由于BeanFactory本身也是一個(gè)bean,當(dāng)請(qǐng)求是BeanFactory這個(gè)bean的時(shí)候围辙,name是帶有&符號(hào)的,而緩存map里面的beanName都是不帶&符號(hào)的
        // 2、name也有可能是bean的一個(gè)別名
        // transformedBeanName方法便是將以上倆種可能的name轉(zhuǎn)化為具體的beanName
        final String beanName = transformedBeanName(name);
        Object bean;

        // Eagerly check singleton cache for manually registered singletons.
        // 從緩存map中獲取bean
        Object sharedInstance = getSingleton(beanName);
        if (sharedInstance != null && args == null) {
            if (logger.isDebugEnabled()) {
                if (isSingletonCurrentlyInCreation(beanName)) {
                    logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
                            "' that is not fully initialized yet - a consequence of a circular reference");
                }
                else {
                    logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
                }
            }
            // 這里面對(duì)sharedInstance做了一些處理赎败,分為以下幾種情況:
            // 1、如果name是以&符號(hào)開頭(代表想要獲取的是FactoryBean)蠢甲,
            // 但是sharedInstance是NullBean僵刮,或者sharedInstance根本不是一個(gè)FactoryBean,
            // 那么此時(shí)返回一個(gè)NullBean鹦牛,或者拋出異常
            // 2搞糕、如果sharedInstance是一個(gè)普通bean,或者name是以&開頭能岩,代表想要獲取FactoryBean本身寞宫,此時(shí)直接返回
            // 3、其他情況下拉鹃,調(diào)用getObject方法獲取真正的bean實(shí)例
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }

        else {
            // Fail if we're already creating this bean instance:
            // We're assumably within a circular reference.
            // BeanFactory 無法處理Prototype類型的bean的循環(huán)依賴問題
            if (isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }

            // Check if bean definition exists in this factory.
            // 獲取父BeanFactory
            BeanFactory parentBeanFactory = getParentBeanFactory();
            // 父BeanFactory不為空且<beanName,beanDefinition>的map中不含有該beanName(也就是說該bean對(duì)應(yīng)的BeanDefinition還未進(jìn)行解析),那么將獲取bean實(shí)例委托給父BeanFactory
            if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
                // Not found -> check parent.
                // 將可能是別名的name解析成具體的beanName辈赋,如果name以&開頭鲫忍,那么返回值也將帶有&符號(hào)
                String nameToLookup = originalBeanName(name);
                // 如果是AbstractBeanFactory類型,遞歸調(diào)用doGetBean方法
                if (parentBeanFactory instanceof AbstractBeanFactory) {
                    return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                            nameToLookup, requiredType, args, typeCheckOnly);
                }
                else if (args != null) {
                    // Delegation to parent with explicit args.
                    // 如果參數(shù)不為空钥屈,調(diào)用接口層次的getBean悟民,由getBean決定具體的實(shí)現(xiàn)方法
                    // (getBean是一個(gè)通用接口聲明,具體有多中實(shí)現(xiàn)篷就,包含但不止AbstractBeanFactory)
                    return (T) parentBeanFactory.getBean(nameToLookup, args);
                }
                else {
                    // No args -> delegate to standard getBean method.
                    // 參數(shù)為空射亏,與參數(shù)不為空邏輯一致,只不過交由getBean的另外一個(gè)重載方法去處理
                    return parentBeanFactory.getBean(nameToLookup, requiredType);
                }
            }

            // typeCheckOnly
            // true表示doGetBean僅僅是為了做類型檢查
            // false表示為了實(shí)際使用bean實(shí)例竭业,如果是實(shí)際使用bean實(shí)例智润,則有必要標(biāo)識(shí)為已創(chuàng)建,以讓緩存起到作用
            if (!typeCheckOnly) {
                // 將beanName加入到alreadyCreated集合中未辆,標(biāo)識(shí)為已創(chuàng)建窟绷,并且將beanDefinition的stale屬性設(shè)置為true,防止創(chuàng)建期間元數(shù)據(jù)發(fā)生變更
                markBeanAsCreated(beanName);
            }

            try {
                // 將父bean和子bean合并咐柜,可能是從緩存中獲取
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                // 檢查mbd是否是抽象兼蜈,若是,拋出異常
                checkMergedBeanDefinition(mbd, beanName, args);

                // Guarantee initialization of beans that the current bean depends on.
                // 保證bean下的depends on已經(jīng)實(shí)例化
                // 注意depends on和循環(huán)依賴的區(qū)別
                // <bean id="beanOne" class="ExampleBean" depends-on="manager,accountDao">
                //     <property name="manager" ref="manager" />
                // </bean>
                // 使用@Autowired的時(shí)候拙友,我們注入的是property
                String[] dependsOn = mbd.getDependsOn();
                if (dependsOn != null) {
                    for (String dep : dependsOn) {
                        // 不允許循環(huán)depends on
                        if (isDependent(beanName, dep)) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                        }
                        // 注冊depends on關(guān)系为狸,注冊之后其他bean創(chuàng)建的時(shí)候才能通過isDependent方法檢查循環(huán)depends on
                        registerDependentBean(dep, beanName);
                        try {
                            // 創(chuàng)建depend on實(shí)例
                            getBean(dep);
                        }
                        catch (NoSuchBeanDefinitionException ex) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                        }
                    }
                }

                // Create bean instance.
                if (mbd.isSingleton()) {
                    // 創(chuàng)建單例類型的bean實(shí)例
                    // getSingleton方法后面解析
                    sharedInstance = getSingleton(beanName, () -> {
                        try {
                            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.
                            // 在早期的創(chuàng)建過程中,可能為了解決循環(huán)引用問題遗契,導(dǎo)致beanName加入了singleton緩存中辐棒,此時(shí)需要移除該緩存
                            destroySingleton(beanName);
                            throw ex;
                        }
                    });
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }

                else if (mbd.isPrototype()) {
                    // It's a prototype -> create a new instance.
                    // 創(chuàng)建prototype類型的bean實(shí)例
                    Object prototypeInstance = null;
                    try {
                        // 寫入prototype類型的依賴關(guān)系,以便上述的isPrototypeCurrentlyInCreation方法做出攔截
                        beforePrototypeCreation(beanName);
                        prototypeInstance = createBean(beanName, mbd, args);
                    }
                    finally {
                        // 創(chuàng)建完畢則可以刪除prototype類型的依賴關(guān)系
                        afterPrototypeCreation(beanName);
                    }
                    bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                }

                else {
                    // 創(chuàng)建其他類型的bean實(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 {
                        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) {
                // 創(chuàng)建失敗的情況下刪除緩存數(shù)據(jù)
                cleanupAfterBeanCreationFailure(beanName);
                throw ex;
            }
        }

        // Check if required type matches the type of the actual bean instance.
        // 檢查創(chuàng)建出來的bean實(shí)例是否是要求的類型
        if (requiredType != null && !requiredType.isInstance(bean)) {
            try {
                // 不是的情況下牍蜂,進(jìn)行類型裝換
                T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
                if (convertedBean == null) {
                    throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
                }
                return convertedBean;
            }
            catch (TypeMismatchException ex) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Failed to convert bean '" + name + "' to required type '" +
                            ClassUtils.getQualifiedName(requiredType) + "'", ex);
                }
                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
            }
        }
        return (T) bean;
    }

方法很長涉瘾,總結(jié)起來主要做了以下幾點(diǎn):

  • 通過transformedBeanName做了beanName的轉(zhuǎn)換
  • 從緩存中獲取bean實(shí)例
    • 緩存不為空,通過getObjectForBeanInstance獲取bean實(shí)例
    • 緩存為空捷兰,創(chuàng)建bean
  • 將獲取到的bean實(shí)例與requiredType做校驗(yàn)立叛,必要時(shí)進(jìn)行類型轉(zhuǎn)換

下面逐個(gè)解析


2. 轉(zhuǎn)換beanName

方法一開始傳進(jìn)來的beanName可能有以下倆種情況:

  • 以&開頭的name,代表獲取FactoryBean這個(gè)bean
  • 別名

而<beanName贡茅,bean>的緩存中秘蛇,beanName是不帶&符號(hào)的非別名beanName,這時(shí)候需要將beanName轉(zhuǎn)化為真正的beanName顶考,方便后面再緩存中獲取beanName對(duì)應(yīng)的bean:

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

通過別名獲取到真正的beanName:

    public String canonicalName(String name) {
        String canonicalName = name;
        // Handle aliasing...
        String resolvedName;
        do {
            resolvedName = this.aliasMap.get(canonicalName);
            if (resolvedName != null) {
                canonicalName = resolvedName;
            }
        }
        while (resolvedName != null);
        return canonicalName;
    }

對(duì)name做去除&符號(hào)的處理:

    public static String transformedBeanName(String name) {
        Assert.notNull(name, "'name' must not be null");
        // 如果name不是以&開頭赁还,直接返回
        if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
            return name;
        }
        // 否則,從transformedBeanNameCache中獲取name對(duì)應(yīng)的value驹沿,如果value為空艘策,對(duì)beanName剔除&前綴,之后寫入transformedBeanNameCache
        return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
            do {
                beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
            }
            while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
            return beanName;
        });
    }

其中渊季,Map#computeIfAbsent定義如下:

default V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction)

含義是如果map中的key對(duì)應(yīng)的value為空朋蔫,那么使用mappingFunction生產(chǎn)一個(gè)值罚渐,作為value,并寫入map中


3. AbstractBeanFactory#getSingleton

    @Nullable
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        // 從緩存中讀取beanName對(duì)應(yīng)的bean
        Object singletonObject = this.singletonObjects.get(beanName);
        // 如果不存在該beanName對(duì)應(yīng)的bean驯妄,并且該bean處于創(chuàng)建之中(由于循環(huán)依賴導(dǎo)致beanName被寫入singletonsCurrentlyInCreation)荷并,那么通過早期引用來解決循環(huán)依賴問題
        // 寫入singletonsCurrentlyInCreation這一步發(fā)生在AbstractBeanFactory#doGetBean#createBean#doCreateBean#populateBean#applyPropertyValues
        // #resolveValueIfNecessary#resolveInnerBean#getObjectFromFactoryBean#beforeSingletonCreation
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            synchronized (this.singletonObjects) {
                // 從早期引用中獲取bean
                singletonObject = this.earlySingletonObjects.get(beanName);
                // 早期引用不存在bean且允許使用早期引用
                if (singletonObject == null && allowEarlyReference) {
                    // 獲取bean創(chuàng)建工廠
                    ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                    if (singletonFactory != null) {
                        // 調(diào)用getObject方法創(chuàng)建bean
                        singletonObject = singletonFactory.getObject();
                        // 寫入早期引用,解決循環(huán)依賴問題
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        // 移除工廠
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }
        return singletonObject;
    }

從緩存中獲取bean青扔,這里涉及到了循環(huán)依賴的處理源织,大致就是如果碰到當(dāng)前獲取的bean處于正在創(chuàng)建中:

isSingletonCurrentlyInCreation

那么說明當(dāng)前bean已經(jīng)處于循環(huán)依賴中,那么寫入earlySingletonObjects中微猖,那么下次進(jìn)來谈息,就可以直接返回對(duì)應(yīng)實(shí)例,從而解決早期引用問題凛剥。

舉例來說黎茎,A依賴B,B依賴A当悔,首先創(chuàng)建A,將A寫入正在創(chuàng)建的bean集合isSingletonCurrentlyInCreation中踢代,然后發(fā)現(xiàn)依賴B盲憎,接著去創(chuàng)建B,發(fā)現(xiàn)依賴A胳挎,這時(shí)發(fā)現(xiàn)A處于isSingletonCurrentlyInCreation中饼疙,那么將A寫入早期引用集合earlySingletonObjects中,然后完成創(chuàng)建B流程慕爬,接著也就完成創(chuàng)建A流程


4. AbstractBeanFactory#getObjectForBeanInstance

查看源碼之前窑眯,有個(gè)疑問,既然已經(jīng)從緩存中獲取到了實(shí)例医窿,如果還要通過getObjectForBeanInstance進(jìn)行處理磅甩?這是因?yàn)閺木彺嬷蝎@取到實(shí)例是最原始的實(shí)例,如果通過getObjectForBeanInstance進(jìn)行加工得到我們想要的實(shí)例

    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.
        // 如果name以&開頭
        if (BeanFactoryUtils.isFactoryDereference(name)) {
            // NullBean類型直接返回
            if (beanInstance instanceof NullBean) {
                return beanInstance;
            }
            // 以&開頭代表想要獲取FactoryBean實(shí)例姥卢,但得到的實(shí)例實(shí)際上不是FactoryBean實(shí)例卷要,拋出異常
            if (!(beanInstance instanceof FactoryBean)) {
                throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
            }
            if (mbd != null) {
                mbd.isFactoryBean = true;
            }
            return beanInstance;
        }

        // 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.
        // 普通類型bean實(shí)例,直接返回該實(shí)例
        if (!(beanInstance instanceof FactoryBean)) {
            return beanInstance;
        }

        // 如果上述均不滿足独榴,調(diào)用BeanFactory工廠getObject方法創(chuàng)建bean
        Object object = null;
        if (mbd != null) {
            mbd.isFactoryBean = true;
        }
        else {
            // 從factoryBeanObjectCache緩存中獲取緩存
            object = getCachedObjectForFactoryBean(beanName);
        }
        if (object == null) {
            // Return bean instance from factory.
            FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
            // Caches object obtained from FactoryBean if it is a singleton.
            if (mbd == null && containsBeanDefinition(beanName)) {
                // 合并BeanDefinition
                mbd = getMergedLocalBeanDefinition(beanName);
            }
            // synthetic字面意思是合成的僧叉,true代表非應(yīng)用本身創(chuàng)建的bean,如使用<aop:config>創(chuàng)建的自動(dòng)代理bean
            boolean synthetic = (mbd != null && mbd.isSynthetic());
            // 繼續(xù)調(diào)用getObjectFromFactoryBean方法創(chuàng)建bean
            object = getObjectFromFactoryBean(factory, beanName, !synthetic);
        }
        return object;
    }

可以分成三個(gè)部分查看流程:

  • 首先處理name以&開頭的情況棺榔,如果是NullBean瓶堕,直接返回實(shí)例beanInstance;如果對(duì)應(yīng)實(shí)例beanInstance不是FactoryBean類型症歇,拋出異常郎笆;否則谭梗,返回實(shí)例beanInstance
  • 如果是普通bean,直接返回對(duì)應(yīng)實(shí)例
  • 如果是其他情況题画,通過getObjectFromFactoryBean獲得bean實(shí)例

5. AbstractBeanFactory#getObjectFromFactoryBean

    protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
        // 單例模式默辨,有使用緩存
        // containsSingleton方法判斷了singletonObjects是否包含beanName,而singletonObjects在doGetBean中sharedInstance為空的分支中苍息,通過getSingleton方法進(jìn)行了put
        // 而這一步是sharedInstance不為空的分支走進(jìn)來的缩幸,所以這時(shí)候singletonObjects應(yīng)該是已經(jīng)包含beanName了
        if (factory.isSingleton() && containsSingleton(beanName)) {
            // getSingletonMutex返回singletonObjects對(duì)象,單例模式在并發(fā)情況下需要保證只創(chuàng)建一個(gè)實(shí)例竞思,所以需要對(duì)singletonObjects加鎖
            synchronized (getSingletonMutex()) {
                Object object = this.factoryBeanObjectCache.get(beanName);
                if (object == null) {
                    // doGetObjectFromFactoryBean調(diào)用了getObject方法
                    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)
                    // TODO
                    // 沒看懂這幾句代碼
                    // 貌似是上述的getObject方法調(diào)用期間表谊,只會(huì)在不存在實(shí)例的情況下才創(chuàng)建實(shí)例并保存,所以這里要再次獲取一次盖喷,保證獲取的是第一次創(chuàng)建的實(shí)例
                    Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
                    if (alreadyThere != null) {
                        object = alreadyThere;
                    }
                    else {
                        // 進(jìn)入這個(gè)分支意味著object是第一次創(chuàng)建的實(shí)例爆办,這時(shí)候需要通過shouldPostProcess判斷是否進(jìn)行后置處理
                        // PostProcess中文含義便是"后處理"
                        if (shouldPostProcess) {
                            // TODO
                            // 不是很懂這里判斷的含義
                            if (isSingletonCurrentlyInCreation(beanName)) {
                                // Temporarily return non-post-processed object, not storing it yet..
                                return object;
                            }
                            // 將beanName加入singletonsCurrentlyInCreation
                            beforeSingletonCreation(beanName);
                            try {
                                // 應(yīng)用后置處理方法
                                object = postProcessObjectFromFactoryBean(object, beanName);
                            }
                            catch (Throwable ex) {
                                throw new BeanCreationException(beanName,
                                        "Post-processing of FactoryBean's singleton object failed", ex);
                            }
                            finally {
                                // 將beanName從singletonsCurrentlyInCreation移除
                                afterSingletonCreation(beanName);
                            }
                        }
                        if (containsSingleton(beanName)) {
                            // 已創(chuàng)建的實(shí)例寫入緩存
                            this.factoryBeanObjectCache.put(beanName, object);
                        }
                    }
                }
                return object;
            }
        }
        else {
            // 原型模式,不使用緩存课梳,每次重新創(chuàng)建
            Object object = doGetObjectFromFactoryBean(factory, beanName);
            if (shouldPostProcess) {
                try {
                    object = postProcessObjectFromFactoryBean(object, beanName);
                }
                catch (Throwable ex) {
                    throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
                }
            }
            return object;
        }
    }

該段代碼主要是做了一些后置處理距辆,核心在于doGetObjectFromFactoryBean

6. AbstractBeanFactory#doGetObjectFromFactoryBean

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

        Object object;
        try {
            if (System.getSecurityManager() != null) {
                // 安全方面的處理
                AccessControlContext acc = getAccessControlContext();
                try {
                    object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
                }
                catch (PrivilegedActionException pae) {
                    throw pae.getException();
                }
            }
            else {
                // 調(diào)用getObject方法創(chuàng)建實(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)) {
                throw new BeanCurrentlyInCreationException(
                        beanName, "FactoryBean which is currently in creation returned null from getObject");
            }
            object = new NullBean();
        }
        return object;
    }

7. AbstractBeanFactory#getMergedLocalBeanDefinition

    protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
        // Quick check on the concurrent map first, with minimal locking.
        // 查閱緩存
        RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
        if (mbd != null && !mbd.stale) {
            return mbd;
        }
        // getBeanDefinition(beanName):從beanDefinitionMap獲取BeanDefinition
        return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
    }
    protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd)
            throws BeanDefinitionStoreException {

        return getMergedBeanDefinition(beanName, bd, null);
    }
    //  <bean id="hello" class="xyz.coolblog.innerbean.Hello">
    //    <property name="content" value="hello"/>
    //  </bean>
    //
    //  <bean id="hello-child" parent="hello">
    //    <property name="content" value="I`m hello-child"/>
    //  </bean>
    // spring支持通過以上方式進(jìn)行配置繼承,子類從而可以覆蓋或者繼承父類的配置
    protected RootBeanDefinition getMergedBeanDefinition(
            String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
            throws BeanDefinitionStoreException {

        synchronized (this.mergedBeanDefinitions) {
            RootBeanDefinition mbd = null;
            RootBeanDefinition previous = null;

            // Check with full lock now in order to enforce the same merged instance.
            if (containingBd == null) {
                mbd = this.mergedBeanDefinitions.get(beanName);
            }


            // stale:陳舊暮刃,該屬性用于標(biāo)示是否需要進(jìn)行重新合并
            if (mbd == null || mbd.stale) {
                previous = mbd;
                if (bd.getParentName() == null) {
                    // 沒有父類
                    // Use copy of given root bean definition.
                    if (bd instanceof RootBeanDefinition) {
                        mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
                    }
                    else {
                        mbd = new RootBeanDefinition(bd);
                    }
                }
                else {
                    // 有父類跨算,進(jìn)行合并
                    // Child bean definition: needs to be merged with parent.
                    BeanDefinition pbd;
                    try {
                        String parentBeanName = transformedBeanName(bd.getParentName());
                        if (!beanName.equals(parentBeanName)) {
                            // 子beanName和父beanName不同的情況下
                            // 遞歸調(diào)用,獲取parentBeanDefinition
                            pbd = getMergedBeanDefinition(parentBeanName);
                        }
                        else {
                            // 子beanName和父beanName相同的情況下
                            // TODO 沒看懂
                            // 看起來也是一個(gè)遞歸調(diào)用椭懊,但是只在parent是ConfigurableBeanFactory的情況下進(jìn)行遞歸調(diào)用
                            // 遞歸后最終還是得回到這個(gè)方法诸蚕,并且此時(shí)并非是ConfigurableBeanFactory類型(也就是不再進(jìn)入這個(gè)分支)
                            BeanFactory parent = getParentBeanFactory();
                            if (parent instanceof ConfigurableBeanFactory) {
                                pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
                            }
                            else {
                                throw new NoSuchBeanDefinitionException(parentBeanName,
                                        "Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
                                        "': cannot be resolved without a ConfigurableBeanFactory parent");
                            }
                        }
                    }
                    catch (NoSuchBeanDefinitionException ex) {
                        throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
                                "Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
                    }
                    // Deep copy with overridden values.
                    // 覆蓋或者繼承父類的配置
                    mbd = new RootBeanDefinition(pbd);
                    mbd.overrideFrom(bd);
                }

                // Set default singleton scope, if not configured before.
                // 沒配置的情況下設(shè)置默認(rèn)singleton scope
                if (!StringUtils.hasLength(mbd.getScope())) {
                    mbd.setScope(SCOPE_SINGLETON);
                }

                // A bean contained in a non-singleton bean cannot be a singleton itself.
                // Let's correct this on the fly here, since this might be the result of
                // parent-child merging for the outer bean, in which case the original inner bean
                // definition will not have inherited the merged outer bean's singleton status.
                // 容器是非singleton并且bean是singleton的情況下,bean不可能是singleton氧猬,此時(shí)需要進(jìn)行覆蓋
                if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
                    mbd.setScope(containingBd.getScope());
                }

                // Cache the merged bean definition for the time being
                // (it might still get re-merged later on in order to pick up metadata changes)
                // 開啟緩存模式的情況下進(jìn)行緩存
                if (containingBd == null && isCacheBeanMetadata()) {
                    this.mergedBeanDefinitions.put(beanName, mbd);
                }
            }
            if (previous != null) {
                // 重新合并背犯,使用previous的配置覆蓋mbd的配置
                copyRelevantMergedBeanDefinitionCaches(previous, mbd);
            }
            return mbd;
        }
    }

主要邏輯就是對(duì)BeanDefinition整合一下parentBeanDefinition,對(duì)于BeanDefnition盅抚,可以戳《Spring源碼解析(一)-BeanDefinition加載》

總結(jié)

畫個(gè)流程圖理清一下doGetBean的流程

doGetBean方法流程

本文僅講述了獲取單例bean的流程漠魏,流程圖中createBean等源碼的解析放置于下一章節(jié)《Spring源碼解析(八)-創(chuàng)建單例bean》

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市妄均,隨后出現(xiàn)的幾起案子蛉幸,更是在濱河造成了極大的恐慌,老刑警劉巖丛晦,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件奕纫,死亡現(xiàn)場離奇詭異,居然都是意外死亡烫沙,警方通過查閱死者的電腦和手機(jī)匹层,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人升筏,你說我怎么就攤上這事撑柔。” “怎么了您访?”我有些...
    開封第一講書人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵铅忿,是天一觀的道長。 經(jīng)常有香客問我灵汪,道長檀训,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任享言,我火速辦了婚禮峻凫,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘览露。我一直安慰自己荧琼,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開白布差牛。 她就那樣靜靜地躺著命锄,像睡著了一般。 火紅的嫁衣襯著肌膚如雪偏化。 梳的紋絲不亂的頭發(fā)上脐恩,一...
    開封第一講書人閱讀 49,007評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音夹孔,去河邊找鬼。 笑死析孽,一個(gè)胖子當(dāng)著我的面吹牛搭伤,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播袜瞬,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼怜俐,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了邓尤?” 一聲冷哼從身側(cè)響起拍鲤,我...
    開封第一講書人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎汞扎,沒想到半個(gè)月后季稳,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡澈魄,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年景鼠,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片痹扇。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡铛漓,死狀恐怖溯香,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情浓恶,我是刑警寧澤玫坛,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布,位于F島的核電站包晰,受9級(jí)特大地震影響湿镀,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜杜窄,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一肠骆、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧塞耕,春花似錦蚀腿、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至筛谚,卻和暖如春磁玉,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背驾讲。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來泰國打工蚊伞, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人吮铭。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓时迫,卻偏偏與公主長得像,于是被迫代替她去往敵國和親谓晌。 傳聞我的和親對(duì)象是個(gè)殘疾皇子掠拳,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345