Spring源碼閱讀----Spring IoC之finishBeanFactoryInitialization及Spring 如何解決循環(huán)依賴

概述

前面我們從registerBeanPostProcessors方法解析的時(shí)候,已經(jīng)提到了finishBeanFactoryInitialization方法脂崔。我們先越過中間的消息資源初始化以及事件監(jiān)聽的部分餐曹,來解析一下finishBeanFactoryInitialization這個(gè)方法憋他,因?yàn)槲覀儚那懊嬉呀?jīng)知道Spring IoC最重要部分就在于:obtainFreshBeanFactory国章、invokeBeanFactoryPostProcessors褐隆、registerBeanPostProcessors 和finishBeanFactoryInitialization 這四個(gè)方法,而finishBeanFactoryInitialization 又是Spring IoC的核心侦锯。
在finishBeanFactoryInitialization 方法里驼鞭,會(huì)實(shí)例化所有剩余的非懶加載單例 bean(包括一些內(nèi)部的 bean、實(shí)現(xiàn)了 BeanFactoryPostProcessor 接口的 bean率触、實(shí)現(xiàn)了 BeanPostProcessor 接口的 bean终议,以及其他的非懶加載單例 bean) , 之前注冊(cè)了的BeanPostProcessor 實(shí)現(xiàn)類也是在這里被調(diào)用執(zhí)行其方法的葱蝗。

finishBeanFactoryInitialization

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
        // Initialize conversion service for this context.
        // 為上下文初始化轉(zhuǎn)換服務(wù)
        if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
                beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
            beanFactory.setConversionService(
                    beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
        }

        // Register a default embedded value resolver if no bean post-processor
        // (such as a PropertyPlaceholderConfigurer bean) registered any before:
        // at this point, primarily for resolution in annotation attribute values.
        // 如果beanFactory之前沒有注冊(cè)嵌入值解析器,則注冊(cè)默認(rèn)的嵌入值解析器:主要用于注解屬性值的解析细燎。
        if (!beanFactory.hasEmbeddedValueResolver()) {
            beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
        }

        // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
        // 獲取LoadTimeWeaverAware類型的bean名稱
        // 遍歷初始化LoadTimeWeaverAware Bean實(shí)例對(duì)象
        String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
        for (String weaverAwareName : weaverAwareNames) {
            getBean(weaverAwareName);
        }

        // Stop using the temporary ClassLoader for type matching.
        beanFactory.setTempClassLoader(null);

        // Allow for caching all bean definition metadata, not expecting further changes.
        // 凍結(jié)配置两曼,允許緩存所有bean定義元數(shù)據(jù),所有bean定義不會(huì)被修改或進(jìn)一步后處理
        beanFactory.freezeConfiguration();

        // Instantiate all remaining (non-lazy-init) singletons.
        //注釋1. 實(shí)例化所有剩余(非懶加載)單例對(duì)象
        beanFactory.preInstantiateSingletons();
    }

執(zhí)行步驟按方法中的注釋往下走玻驻,比較清晰悼凑,最后到達(dá)最后一步實(shí)例化偿枕。具體來看最后一步的實(shí)例化步驟。

注釋1. 實(shí)例化所有剩余(非懶加載)單例對(duì)象 (見源碼解析1)
【源碼解析1】 beanFactory.preInstantiateSingletons
我們知道beanFactory是DefaultListableBeanFactory類型户辫,所以preInstantiateSingletons方法源碼如下:

public void preInstantiateSingletons() throws BeansException {
        if (logger.isTraceEnabled()) {
            logger.trace("Pre-instantiating singletons in " + this);
        }

        // Iterate over a copy to allow for init methods which in turn register new bean definitions.
        // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
        //創(chuàng)建beanDefinitionNames的副本beanNames用于后續(xù)的遍歷渐夸,以允許init等方法注冊(cè)新的bean定義
        List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

        // Trigger initialization of all non-lazy singleton beans...
        for (String beanName : beanNames) {

            //注釋1. 獲取beanName對(duì)應(yīng)的MergedBeanDefinition
            RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);

            // 判斷bd這個(gè)Bean實(shí)例:不是抽象類 && 是單例 && 不是懶加載
            if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {

                //注釋2. 判斷beanName對(duì)應(yīng)的bean是否為FactoryBean
                if (isFactoryBean(beanName)) {

                    //注釋2-1. getBean('&'+beanName)將得到bean本身
                    //通過getBean(beanName)拿到的是FactoryBean創(chuàng)建的Bean實(shí)例
                    Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
                    if (bean instanceof FactoryBean) {
                        //判斷它是不是FactoryBean類型,然后獲取FactoryBean實(shí)例
                        final FactoryBean<?> factory = (FactoryBean<?>) bean;

                        // 急切初始化標(biāo)識(shí)
                        boolean isEagerInit;
                        if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                            isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
                                            ((SmartFactoryBean<?>) factory)::isEagerInit,
                                    getAccessControlContext());
                        }
                        else {
                            isEagerInit = (factory instanceof SmartFactoryBean &&
                                    ((SmartFactoryBean<?>) factory).isEagerInit());
                        }

                        //注釋2-2. 如果需急切初始化渔欢,則通過getBean(beanName)獲取bean實(shí)例
                        if (isEagerInit) {
                            getBean(beanName);
                        }
                    }
                }
                else {
                    //注釋2-3 如果beanName對(duì)應(yīng)的bean不是FactoryBean墓塌,只是普通Bean,通過getBean(beanName)獲取bean實(shí)例
                    getBean(beanName);
                }
            }
        }

        // Trigger post-initialization callback for all applicable beans...
        // 注釋3. 遍歷beanNames奥额,觸發(fā)post-initialization 回調(diào)
        for (String beanName : beanNames) {

            // 獲取beanName對(duì)應(yīng)的單例bean實(shí)例
            Object singletonInstance = getSingleton(beanName);

            //判斷singletonInstance是否實(shí)現(xiàn)了SmartInitializingSingleton接口
            if (singletonInstance instanceof SmartInitializingSingleton) {
                final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;

                    //觸發(fā)SmartInitializingSingleton實(shí)現(xiàn)類的afterSingletonsInstantiated方法
                if (System.getSecurityManager() != null) {
                    AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                        smartSingleton.afterSingletonsInstantiated();
                        return null;
                    }, getAccessControlContext());
                }
                else {
                    smartSingleton.afterSingletonsInstantiated();
                }
            }
        }
    }

整個(gè)流程按注釋順序下來,比較清晰苫幢。這里出現(xiàn)了兩個(gè)比較重要的名稱:MergedBeanDefinition 和FactoryBean后面一一解釋。
其中需要解析的部分如下:
注釋1. 獲取beanName對(duì)應(yīng)的MergedBeanDefinition (見源碼解析2)
注釋2. 判斷beanName對(duì)應(yīng)的bean是否為FactoryBean垫挨,isFactoryBean方法放最后解釋韩肝。 (見源碼解析4)
注釋2-2 、注釋2-3 都為getBean(beanName)獲取bean實(shí)例九榔,前者為FactoryBean實(shí)例哀峻,后者為普通bean實(shí)例。getBean是一個(gè)非常重要的方法,將在后邊詳細(xì)解析哲泊。

注釋3. 遍歷 beanNames剩蟀,觸發(fā)所有 SmartInitializingSingleton 的后初始化回調(diào),這是 Spring 提供的一個(gè)擴(kuò)展點(diǎn)攻旦,在所有非懶加載單例實(shí)例化結(jié)束后調(diào)用

【源碼解析2】 AbstractBeanFactory類中的getMergedLocalBeanDefinition方法:

    // 方法1
    protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {

        // Quick check on the concurrent map first, with minimal locking.
        //先檢查beanName對(duì)應(yīng)的MergedBeanDefinition是否存在于緩存中
        RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
        if (mbd != null) {

            // 存在喻旷,則返回緩存
            return mbd;
        }

        //不存在,則通過getBeanDefinition獲取BeanDefinition,然后通過beanName牢屋、BeanDefinition 獲取MergedBeanDefinition
        return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
    }

    // 方法2 它只是個(gè)適配器且预,交給方法3執(zhí)行
    protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd)
            throws BeanDefinitionStoreException {

        return getMergedBeanDefinition(beanName, bd, null);
    }

    // 方法3,核心方法
    protected RootBeanDefinition getMergedBeanDefinition(
            String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
            throws BeanDefinitionStoreException {

         // 加同步鎖
        synchronized (this.mergedBeanDefinitions) {

            // 定義一個(gè)mbd返回值,用于存儲(chǔ)bd的MergedBeanDefinition
            RootBeanDefinition mbd = null;

            // Check with full lock now in order to enforce the same merged instance.
            if (containingBd == null) {

                // 檢查beanName對(duì)應(yīng)的MergedBeanDefinition是否存在于緩存中
                mbd = this.mergedBeanDefinitions.get(beanName);
            }

            // 如果beanName對(duì)應(yīng)的MergedBeanDefinition不存在于緩存中
            if (mbd == null) {

                //如果bd的parentName為空
                if (bd.getParentName() == null) {
                    // Use copy of given root bean definition.
                    //如果bd的類型為RootBeanDefinition烙无,則bd的MergedBeanDefinition就是bd本身锋谐,則直接克隆一個(gè)副本
                    if (bd instanceof RootBeanDefinition) {
                        mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
                    }
                    else {
                        //否則,將bd作為參數(shù)截酷,創(chuàng)建一個(gè)RootBeanDefinition對(duì)象
                        mbd = new RootBeanDefinition(bd);
                    }
                }
                else {
                    // Child bean definition: needs to be merged with parent.
                    //注釋1. 若bd的parentName不為空涮拗,bd存在父定義,需要與父定義合并
                    BeanDefinition pbd;
                    try {

                        //注釋1-1. 獲取父定義的beanName
                        String parentBeanName = transformedBeanName(bd.getParentName());

                        //注釋1-2. 如果父定義的beanName與該bean的beanName不同
                        if (!beanName.equals(parentBeanName)) {
                            //注釋1-2-1. 獲取父定義的MergedBeanDefinition(因?yàn)楦付x也可能有父定義迂苛,即向上獲取合并定義...)
                            pbd = getMergedBeanDefinition(parentBeanName);
                        }
                        else {
                            //注釋1-2-2. 如果父定義的beanName與bd的beanName相同三热,則拿到父BeanFactory
                            //只有在存在父BeanFactory的情況下,才允許父定義beanName與自己相同三幻,否則就是將自己設(shè)置為父定義
                            BeanFactory parent = getParentBeanFactory();
                            if (parent instanceof ConfigurableBeanFactory) {
                                //注釋1-2-3. 如果父BeanFactory是ConfigurableBeanFactory就漾,則通過父BeanFactory獲取父定義的MergedBeanDefinition
                                pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
                            }
                            else {
                                //注釋1-2-4. 如果父BeanFactory不是ConfigurableBeanFactory,則拋異常
                                throw new NoSuchBeanDefinitionException(parentBeanName,
                                        "Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
                                        "': cannot be resolved without an AbstractBeanFactory parent");
                            }
                        }
                    }
                    catch (NoSuchBeanDefinitionException ex) {
                        throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
                                "Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
                    }
                    // Deep copy with overridden values.
                    //注釋1-3. 深拷貝 覆蓋值
                    //使用父定義pbd構(gòu)建一個(gè)新的RootBeanDefinition對(duì)象
                    mbd = new RootBeanDefinition(pbd);

                    //使用bd覆蓋父定義
                    mbd.overrideFrom(bd);
                }

                // Set default singleton scope, if not configured before.
                if (!StringUtils.hasLength(mbd.getScope())) {
                    //注釋2. 如果沒有配置scope念搬,則設(shè)置成默認(rèn)的singleton
                    mbd.setScope(RootBeanDefinition.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.
                if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
                    //注釋3. 如果containingBd不為空抑堡,
                    //并且 containingBd不為singleton ,
                    //并且 mbd為singleton摆出,則將mdb的scope設(shè)置為containingBd的scope
                    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)
                if (containingBd == null && isCacheBeanMetadata()) {
                    //注釋4. 將beanName與mbd放到mergedBeanDefinitions緩存,以便之后可以直接使用
                    this.mergedBeanDefinitions.put(beanName, mbd);
                }
            }

            //注釋5. 返回MergedBeanDefinition
            return mbd;
        }
    }

    //方法4. 用戶獲取父類等上層的MergedBeanDefinition
    public BeanDefinition getMergedBeanDefinition(String name) throws BeansException {

                // 獲取真正的beanName(解析別名)
        String beanName = transformedBeanName(name);
        // Efficiently check whether bean definition exists in this factory.
        // 如果當(dāng)前BeanFactory中不存在beanName的Bean定義 && 父beanFactory是ConfigurableBeanFactory
        if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {

            // 則調(diào)用父BeanFactory去獲取beanName的MergedBeanDefinition
            return ((ConfigurableBeanFactory) getParentBeanFactory()).getMergedBeanDefinition(beanName);
        }

        // Resolve merged bean definition locally.
        // 在當(dāng)前BeanFactory中解析beanName的MergedBeanDefinition
        return getMergedLocalBeanDefinition(beanName);
    }

這里出現(xiàn)了一個(gè)新名稱父 BeanFactory首妖,后面一一解釋偎漫。
注釋1-1. 獲取父定義的beanName,使用了transformedBeanName方法來獲取 (見源碼解析3)
注釋1-2-1. 獲取父定義的MergedBeanDefinition(見源碼解析1中的方法4)
注釋1-3. 深拷貝 覆蓋值,合并操作有缆,產(chǎn)生MergedBeanDefinition
注釋4. 將beanName與mbd放到mergedBeanDefinitions緩存象踊,所以方法1執(zhí)行的時(shí)候,有緩存就會(huì)獲取緩存妒貌。

【源碼解析3】 transformedBeanName

    // AbstractBeanFactory類中的transformedBeanName方法
    protected String transformedBeanName(String name) {
                //注釋1將 name 真正解析成真正的 beanName通危,主要是去掉 FactoryBean 里的 “&” 前綴,和解析別名
        return canonicalName(BeanFactoryUtils.transformedBeanName(name));
    }

    // BeanFactoryUtils類中的transformedBeanName方法
    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;
        });
    }

    // SimpleAliasRegistry類中的canonicalName方法
    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;
    }

SimpleAliasRegistry為AbstractBeanFactory父類,canonicalName調(diào)用的是SimpleAliasRegistry中的方法灌曙。FACTORY_BEAN_PREFIX為'&'符,將 name 真正解析成真正的 beanName菊碟,主要是去掉 FactoryBean 里的 “&” 前綴,和解析別名在刺。

好了逆害,我們先來把前面遇到的新名稱解釋一下:
MergedBeanDefinition
MergedBeanDefinition 通過字面意思,可以看出來是 合并的Bean定義蚣驼,在執(zhí)行過程中魄幕,我們遇到了一個(gè)bean定義,它可能有父定義等情況颖杏,有以下幾種情況:

  • 該 BeanDefinition 存在 “父定義”:首先使用 “父定義” 的參數(shù)構(gòu)建一個(gè) RootBeanDefinition纯陨,然后再使用該 BeanDefinition 的參數(shù)來進(jìn)行覆蓋。
  • 該 BeanDefinition 不存在 “父定義”留储,并且該 BeanDefinition 的類型是 RootBeanDefinition:直接返回該 RootBeanDefinition 的一個(gè)克隆翼抠。
  • 該 BeanDefinition 不存在 “父定義”,但是該 BeanDefinition 的類型不是 RootBeanDefinition:使用該 BeanDefinition 的參數(shù)構(gòu)建一個(gè) RootBeanDefinition

BeanDefinition 在之前加載到 BeanFactory 中的時(shí)候获讳,通常是被封裝成 GenericBeanDefinition 或 ScannedGenericBeanDefinition阴颖,但是從這邊之后 bean 的后續(xù)流程處理都是針對(duì) RootBeanDefinition,因此在這邊會(huì)統(tǒng)一將 BeanDefinition 轉(zhuǎn)換成 RootBeanDefinition丐膝。

如果我們使用 XML 配置來注冊(cè) bean量愧,則該 bean 定義會(huì)被封裝成:GenericBeanDefinition;如果我們使用注解的方式來注冊(cè) bean帅矗,也就是<context:component-scan /> 或 @Compoment偎肃,則該 bean 定義會(huì)被封裝成 ScannedGenericBeanDefinition

FactoryBean
通常初學(xué)者比較容易被BeanFactory和FactoryBean攪渾,其實(shí)很容易區(qū)分浑此,前面我們已經(jīng)介紹過BeanFactory接口软棺,是IOC容器或?qū)ο蠊S,它是Spring IOC的基礎(chǔ)尤勋,在Spring中喘落,所有的Bean都是由BeanFactory(也就是IOC容器)來進(jìn)行管理。

一般情況下最冰,Spring通過反射機(jī)制利用bean的class屬性指定實(shí)現(xiàn)類實(shí)例化Bean瘦棋,在某些情況下,實(shí)例化Bean過程比較復(fù)雜暖哨,如果按照傳統(tǒng)的方式赌朋,則需要在<bean>中提供大量的配置信息。配置方式的靈活性是受限的篇裁,這時(shí)采用編碼的方式可能會(huì)得到一個(gè)簡(jiǎn)單的方案沛慢。
FactoryBean,是一種特殊的bean, 它是個(gè)工廠 bean达布,可以自己創(chuàng)建 bean 實(shí)例团甲,如果一個(gè)類實(shí)現(xiàn)了 FactoryBean 接口全陨,則該類可以自己定義創(chuàng)建實(shí)例對(duì)象的方法仑嗅,只需要實(shí)現(xiàn)它的 getObject() 方法。

為了區(qū)分 “FactoryBean” 和 “FactoryBean 創(chuàng)建的 bean 實(shí)例”雄坪,Spring 使用了 “&” 前綴产还。Spring里有很多類實(shí)現(xiàn)了FactoryBean匹厘,那我們找一個(gè) beanName 為 gson的,則 getBean("gson") 獲得的是 MapperFactoryBean 通過 getObject() 方法創(chuàng)建的Gson bean 實(shí)例脐区;而 getBean("&gson") 獲得的是 GsonFactoryBean本身愈诚。

父BeanFactory
在 Spring 中可能存在多個(gè) BeanFactory,多個(gè) BeanFactory 可能存在 “父工廠” 與 “子工廠” 的關(guān)系牛隅。最常見的例子就是:Spring MVC 的 BeanFactory 和 Spring 的 BeanFactory炕柔,通常情況下,Spring 的 BeanFactory 是 “父工廠”倔叼,Spring MVC 的 BeanFactory 是 “子工廠”汗唱,在 Spring 中,子工廠可以使用父工廠的 BeanDefinition丈攒,因而哩罪,如果在當(dāng)前 BeanFactory 中找不到,而又存在父工廠巡验,則會(huì)去父工廠中查找际插。

【源碼解析4】 執(zhí)行的該isFactoryBean方法,在AbstractBeanFactory類中

    // 方法1
    public boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException {

        // 轉(zhuǎn)換beanName,獲取真正的beanName(去掉&前綴显设、解析別名)
        String beanName = transformedBeanName(name);

        //注釋1.  獲取beanName對(duì)應(yīng)的單例bean實(shí)例
        Object beanInstance = getSingleton(beanName, false);
        if (beanInstance != null) {

            //beanInstance存在框弛,則直接判斷其類型是否為FactoryBean
            return (beanInstance instanceof FactoryBean);
        }

        // No singleton instance found -> check bean definition.
        if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {
            // No bean definition found in this factory -> delegate to parent.
            // 如果緩存中不存在此beanName 
            // 并且父beanFactory是ConfigurableBeanFactory,
            // 則調(diào)用父BeanFactory判斷是否為FactoryBean
            return ((ConfigurableBeanFactory) getParentBeanFactory()).isFactoryBean(name);
        }

        //注釋2. 通過MergedBeanDefinition來檢查beanName對(duì)應(yīng)的Bean是否為FactoryBean
        return isFactoryBean(beanName, getMergedLocalBeanDefinition(beanName));
    }

    // 方法2
    protected boolean isFactoryBean(String beanName, RootBeanDefinition mbd) {
        // 拿到beanName對(duì)應(yīng)的Bean實(shí)例的類型
        Class<?> beanType = predictBeanType(beanName, mbd, FactoryBean.class);
        return (beanType != null && FactoryBean.class.isAssignableFrom(beanType));
    }

注釋1. 獲取beanName對(duì)應(yīng)的單例bean實(shí)例(見源碼解析5)
注釋2. 通過 MergedBeanDefinition 來檢查 beanName 對(duì)應(yīng)的 bean 是否為 FactoryBean捕捂。首先通過 getMergedLocalBeanDefinition 方法獲取 beanName 的 MergedBeanDefinition瑟枫,接著調(diào)用 isFactoryBean 來檢查 beanName 對(duì)應(yīng)的 bean 是否為 FactoryBean斗搞。
這里的isFactoryBean 方法為上面方法2,其調(diào)用了predictBeanType方法來獲取beanName對(duì)應(yīng)的Bean實(shí)例的類型(見源碼解析6)慷妙,然后通過isAssignableFrom方法來判斷beanType是否與FactoryBean接口類型相同僻焚。

【源碼解析5】 getSingleton方法,在DefaultSingletonBeanRegistry類中膝擂,

    protected Object getSingleton(String beanName, boolean allowEarlyReference) {

        //從單例對(duì)象緩存中獲取beanName對(duì)應(yīng)的單例對(duì)象
        Object singletonObject = this.singletonObjects.get(beanName);
        // 檢查緩存中是否存在實(shí)例
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {

            // 加鎖進(jìn)行操作虑啤,公共變量都需要加鎖操作,避免多線程并發(fā)修改
            synchronized (this.singletonObjects) {
                // 從早期單例對(duì)象緩存中獲取單例對(duì)象(之所稱成為早期單例對(duì)象架馋,是因?yàn)?                //earlySingletonObjects里的對(duì)象的都是通過提前曝光的ObjectFactory創(chuàng)建出來的狞山,還未進(jìn)行屬性填充等操作)
                singletonObject = this.earlySingletonObjects.get(beanName);

                //如果在早期單例對(duì)象緩存中也沒有,并且允許創(chuàng)建早期單例對(duì)象引用
                if (singletonObject == null && allowEarlyReference) {

                    // 從單例工廠緩存中獲取beanName的單例工廠
                    ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);

                    if (singletonFactory != null) {

                        //如果存在單例對(duì)象工廠叉寂,則通過工廠創(chuàng)建一個(gè)單例對(duì)象
                        singletonObject = singletonFactory.getObject();

                        //將通過單例對(duì)象工廠創(chuàng)建的單例對(duì)象萍启,放到早期單例對(duì)象緩存中
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        //移除該beanName對(duì)應(yīng)的單例對(duì)象工廠,因?yàn)樵搯卫S已經(jīng)創(chuàng)建了一個(gè)實(shí)例對(duì)象办绝,并且放到earlySingletonObjects緩存了
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }

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

主要操作步驟就是檢查下我們要拿的 bean 實(shí)例是否存在于緩存中伊约,如果有就返回緩存中的 bean 實(shí)例,否則就返回 null孕蝉。

Spring 解決循環(huán)依賴的核心就是依賴這里的代碼屡律,所以它是一段比較重要的代碼。

解決循環(huán)依賴邏輯:使用構(gòu)造函數(shù)創(chuàng)建一個(gè) “不完整” 的 bean 實(shí)例(之所以說不完整降淮,是因?yàn)榇藭r(shí)該 bean 實(shí)例還未初始化)超埋,并且提前曝光該 bean 實(shí)例的 ObjectFactory(提前曝光就是將 ObjectFactory 放到 singletonFactories 緩存),通過 ObjectFactory 我們可以拿到該 bean 實(shí)例的引用佳鳖,如果出現(xiàn)循環(huán)引用霍殴,我們可以通過緩存中的 ObjectFactory 來拿到 bean 實(shí)例,從而避免出現(xiàn)循環(huán)引用導(dǎo)致的死循環(huán)系吩。這邊通過緩存中的 ObjectFactory 拿到的 bean 實(shí)例雖然拿到的是 “不完整” 的 bean 實(shí)例来庭,但是由于是單例,所以后續(xù)初始化完成后穿挨,該 bean 實(shí)例的引用地址并不會(huì)變月弛,所以最終我們看到的還是完整 bean 實(shí)例。

這段解決邏輯涉及到了后面的一些內(nèi)容科盛,所以可能會(huì)看的不是很理解帽衙,可以先有個(gè)印象,等把創(chuàng)建 bean 實(shí)例都看完了贞绵,再回過頭來看厉萝,可能會(huì)好理解一點(diǎn)。

另外這個(gè)代碼塊中引進(jìn)了4個(gè)重要緩存:

  • singletonObjects 緩存:beanName -> 單例 bean 對(duì)象。
  • earlySingletonObjects 緩存:beanName -> 單例 bean 對(duì)象谴垫,該緩存存放的是早期單例 bean 對(duì)象章母,可以理解成還未進(jìn)行屬性填充、初始化弹渔。
  • singletonFactories 緩存:beanName -> ObjectFactory胳施。
  • singletonsCurrentlyInCreation 緩存:當(dāng)前正在創(chuàng)建單例 bean 對(duì)象的 beanName 集合。

singletonObjects肢专、earlySingletonObjects、singletonFactories 在這邊構(gòu)成了一個(gè)類似于 “三級(jí)緩存” 的概念焦辅。

【源碼解析6】 predictBeanType方法,在AbstractAutowireCapableBeanFactory類中

    @Override
    @Nullable
    protected Class<?> predictBeanType(String beanName, RootBeanDefinition mbd, Class<?>... typesToMatch) {

        //獲取beanName的類型
        Class<?> targetType = determineTargetType(beanName, mbd, typesToMatch);

        // Apply SmartInstantiationAwareBeanPostProcessors to predict the
        // eventual type after a before-instantiation shortcut.
        // 2.應(yīng)用SmartInstantiationAwareBeanPostProcessors后置處理器博杖,來預(yù)測(cè)實(shí)例化的最終類型,
        // SmartInstantiationAwareBeanPostProcessors繼承了InstantiationAwareBeanPostProcessor筷登,
        // InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法可以改變Bean實(shí)例的類型剃根,
        // 而SmartInstantiationAwareBeanPostProcessors的predictBeanType方法可以預(yù)測(cè)這個(gè)類型
        if (targetType != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
                    SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;

                    //調(diào)用predictBeanType方法
                    Class<?> predicted = ibp.predictBeanType(targetType, beanName);
                    if (predicted != null && (typesToMatch.length != 1 || FactoryBean.class != typesToMatch[0] ||
                            FactoryBean.class.isAssignableFrom(predicted))) {
                        //如果predicted不為空,并且
                        //(typesToMatch長(zhǎng)度不為1或typesToMatch[0]不為FactoryBean.class或predicted是FactoryBean本身前方、子類或子接口)
                        //返回predicted
                        return predicted;
                    }
                }
            }
        }

        //返回beanName的類型
        return targetType;
    }

這邊執(zhí)行的是 AbstractAutowireCapableBeanFactory 里的方法狈醉,而不是 AbstractBeanFactory 里的方法。
通過前面的介紹惠险,我們知道創(chuàng)建的 BeanFactory 為 DefaultListableBeanFactory苗傅,而 DefaultListableBeanFactory 繼承了 AbstractAutowireCapableBeanFactory,因此這邊會(huì)走 AbstractAutowireCapableBeanFactory 的重寫方法班巩。

總結(jié)

通過finishBeanFactoryInitialization方法的解析渣慕,知道這里是如何創(chuàng)建 bean 實(shí)例的,以及bean實(shí)例化之前的一些準(zhǔn)備操作抱慌。主要是引入了 FactoryBean 這一特殊的 bean逊桦,獲取 BeanDefinition 的 MergedBeanDefinition,最后將 BeanDefinition 統(tǒng)一轉(zhuǎn)換成 RootBeanDefinition抑进。

中間還學(xué)習(xí)了Spring如何解決循環(huán)依賴的問題强经,是通過緩存。
Spring 中大量使用了本地緩存寺渗,基本上通過名字和注釋就能理解緩存的作用了匿情。
這里用到的幾個(gè)緩存:

  • mergedBeanDefinitions 緩存:beanName -> 合并的 bean 定義。
  • beanDefinitionMap 緩存:beanName -> BeanDefinition户秤。
  • singletonObjects 緩存:beanName -> 單例 bean 對(duì)象码秉。
  • earlySingletonObjects 緩存:beanName -> 單例 bean 對(duì)象,該緩存存放的是早期單例 bean 對(duì)象鸡号,可以理解成還未進(jìn)行屬性填充转砖、初始化。
  • singletonFactories 緩存:beanName -> ObjectFactory。
  • singletonsCurrentlyInCreation 緩存:當(dāng)前正在創(chuàng)建單例 bean 對(duì)象的 beanName 集合府蔗。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末晋控,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子姓赤,更是在濱河造成了極大的恐慌赡译,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,591評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件不铆,死亡現(xiàn)場(chǎng)離奇詭異蝌焚,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)誓斥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門只洒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人劳坑,你說我怎么就攤上這事毕谴。” “怎么了距芬?”我有些...
    開封第一講書人閱讀 162,823評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵涝开,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我框仔,道長(zhǎng)舀武,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,204評(píng)論 1 292
  • 正文 為了忘掉前任存和,我火速辦了婚禮奕剃,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘捐腿。我一直安慰自己纵朋,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,228評(píng)論 6 388
  • 文/花漫 我一把揭開白布茄袖。 她就那樣靜靜地躺著操软,像睡著了一般。 火紅的嫁衣襯著肌膚如雪宪祥。 梳的紋絲不亂的頭發(fā)上聂薪,一...
    開封第一講書人閱讀 51,190評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音蝗羊,去河邊找鬼藏澳。 笑死,一個(gè)胖子當(dāng)著我的面吹牛耀找,可吹牛的內(nèi)容都是我干的翔悠。 我是一名探鬼主播业崖,決...
    沈念sama閱讀 40,078評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼蓄愁!你這毒婦竟也來了双炕?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,923評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤撮抓,失蹤者是張志新(化名)和其女友劉穎妇斤,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體丹拯,經(jīng)...
    沈念sama閱讀 45,334評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡站超,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,550評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了咽笼。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片顷编。...
    茶點(diǎn)故事閱讀 39,727評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖剑刑,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情双肤,我是刑警寧澤施掏,帶...
    沈念sama閱讀 35,428評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站茅糜,受9級(jí)特大地震影響七芭,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蔑赘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,022評(píng)論 3 326
  • 文/蒙蒙 一狸驳、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧缩赛,春花似錦耙箍、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至旨袒,卻和暖如春汁针,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背砚尽。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工施无, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人必孤。 一個(gè)月前我還...
    沈念sama閱讀 47,734評(píng)論 2 368
  • 正文 我出身青樓猾骡,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子卓练,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,619評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容