Spring IoC源碼分析(四)

一弄息、回顧

上回講到……講到哪了……

先貼代碼回顧一下猬膨,找到其中唯一一行注釋吧尔崔!

public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        prepareRefresh();
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
        prepareBeanFactory(beanFactory);
        try {
            postProcessBeanFactory(beanFactory);
            invokeBeanFactoryPostProcessors(beanFactory);
            initMessageSource();
            initApplicationEventMulticaster();
            onRefresh();
            registerListeners();
            //恭喜你找到了注釋答毫,是的,上次講到這兒了
            finishBeanFactoryInitialization(beanFactory);
            finishRefresh();
        }
        catch (BeansException ex) {
            ……
        }
        finally {
            ……
            resetCommonCaches();
        }
    }
}

上回講到季春,在BeanFactory創(chuàng)建和BeanDefinitions注冊完成后洗搂,spring對BeanFactory進行了一些相關的后續(xù)操作,如執(zhí)行BeanFactoryPostProcessors的方法载弄,注冊一些BeanPostProcessors耘拇,設置事件廣播器等等。今天來講一下重頭戲——finishBeanFactoryInitialization(beanFactory)宇攻,一起點進去看看吧惫叛。

二、finishBeanFactoryInitialization(beanFactory)

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
        // 初始化 conversion service 逞刷,不展開
        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));
        }
        // Resolver相關嘉涌,不展開
        if (!beanFactory.hasEmbeddedValueResolver()) {
            beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
        }
        // AspectJ相關,不展開
        String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
        for (String weaverAwareName : weaverAwareNames) {
            getBean(weaverAwareName);
        }
        // 停止使用暫時的類加載器
        beanFactory.setTempClassLoader(null);
        // 凍結配置夸浅,防止在初始化bean過程中出現干擾
        beanFactory.freezeConfiguration();
        // 初始化所有單例bean仑最,最關鍵的一步,進去看看
        beanFactory.preInstantiateSingletons();
}

三题篷、preInstantiateSingletons()

由于代碼比較長词身,所以忽略一些無關緊要的代碼厅目,在看代碼之前番枚,先想一想,為什么BeanFactory需要初始化單例Bean损敷,有哪些單例Bean是需要在一開始就被初始化的葫笼?帶著這樣的問題來看源碼拗馒,會有更清晰的認知。

public void preInstantiateSingletons() throws BeansException {
   // 這里獲取到了工廠里的所有的beanNames
   List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

   // 要開始從萬花叢中找單例的beanDefinition了
   for (String beanName : beanNames) {
      //獲取BeanDefinition
      RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
      //找出非抽象非懶加載的單例beanDefinition
      if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
         //這里出現了一個新的概念,FactoryBean呈昔,很重要,之后講
         if (isFactoryBean(beanName)) {
            //對bean name加工友绝,用于區(qū)分普通bean和factory bean
            Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
            if (bean instanceof FactoryBean) {
               final FactoryBean<?> factory = (FactoryBean<?>) bean;
               //判斷當前FactoryBean是否是SmartFactoryBean的實現堤尾,這里不影響后續(xù)的閱讀,可以跳過迁客,因此省略了
               boolean isEagerInit;
               if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                  ......
               }
               else {
                   ......
               }
               //getBean方法郭宝,這是重點
               if (isEagerInit) {
                  getBean(beanName);
               }
            }
         }
         //若當前的beanDefinition不是factory bean,則直接調用getBean
         else {
            getBean(beanName);
         }
      }
   }

   // 到這里為止掷漱,所有的非懶加載的singleton beans已經完成了初始化
   // 如果我們定義的單例bean是實現了SmartInitializingSingleton接口粘室,那么當他們在初始化后會在這里得到回調,就不展開了
   for (String beanName : beanNames) {
      Object singletonInstance = getSingleton(beanName);
      if (singletonInstance instanceof SmartInitializingSingleton) {
         final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
         if (System.getSecurityManager() != null) {
            AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
               smartSingleton.afterSingletonsInstantiated();
               return null;
            }, getAccessControlContext());
         }
         else {
            smartSingleton.afterSingletonsInstantiated();
         }
      }
   }
}

上面的代碼雖然冗長卜范,但其實可以發(fā)現其實初始化單例bean的關鍵就在于getBean方法衔统,其實也可以說,初始化所有bean的關鍵就在于getBean,因為在這里只不過是對bean的scope做了篩選先朦。

在對getBean做了解之前缰冤,先看看先前講到的FacotryBean是怎么回事

四、FactoryBean

將FactoryBean翻譯成中文喳魏,就是工廠Bean棉浸,也就是說,這個Bean在初始化以后會變成一個工廠刺彩,這樣就很好理解了~那么這個工廠Bean具體是干什么的迷郑?工廠用來生產什么東西?來看看這個類的注釋

/* Interface to be implemented by objects used within a {@link BeanFactory} which
 * are themselves factories for individual objects. If a bean implements this
 * interface, it is used as a factory for an object to expose, not directly as a
 * bean instance that will be exposed itself.
 *
 * <p><b>NB: A bean that implements this interface cannot be used as a normal bean.</b>
 * A FactoryBean is defined in a bean style, but the object exposed for bean
 * references ({@link #getObject()}) is always the object that it creates.
 */

雖然我也看不懂英語创倔,但是不代表我不能翻譯嗡害,簡單來講,FactoryBean能夠生產并暴露獨特的Bean畦攘,而不是直接將FactoryBean本身暴露出來霸妹,這句話有一點抽象,你可以理解成政府(BeanFactory)建立(初始化)了一家棒冰廠家(FactoryBean)知押,用來生產棒冰給員工(開發(fā)者)降暑叹螟,你得知道員工需要的只是棒冰而并不是廠家本身。

因此罢绽,如果一個類實現了FactoryBean良价,那么你就不能把他當作一個普通Bean來使用明垢,此時打開你的腦洞,想象FactoryBean可以從一個其他的遠程項目中獲取一個對象來作為Bean實例返回史隆,或者更夸張一些泌射,遠程獲取的Bean甚至可以是一個服務熔酷,只需調用這個服務拒秘,便可以讓自己的項目功能瞬間完成躺酒,這讓你又多了一個小時額外的自主學習(摸魚)時間羹应,豈不快哉?

好了好了劫灶,到此為止本昏,是時候看看getBean了涌穆,前面提到getBean是初始化Bean的關鍵

五蒲犬、getBean(beanName)

getBean方法位于AbstractBeanFactory中原叮,該類提供了很多該方法的重載擂送,不過功能其實是一樣的——獲取bean實例嘹吨,來看看這次的主角getBean(String beanName)

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 {
        //傳來的name可能是帶$的FactoryBean或者別名此衅,要轉換一下,不展開了
        final String beanName = transformedBeanName(name);
        //該bean用來作為返回值墨微,關注一下 
        Object bean;

        // 首先檢查是否為已經手動創(chuàng)建的單例bean
        Object sharedInstance = getSingleton(beanName);
        //若是已創(chuàng)建的單例bean欢嘿,則會判斷args炼蹦,args不為空表示創(chuàng)建一個新的bean并返回掐隐,比如讓FactoryBean返回一個新的bean
        if (sharedInstance != null && args == null) {
            if (logger.isDebugEnabled()) {
                if (isSingletonCurrentlyInCreation(beanName)) {
                    ......
                }
                else {
                    ......
                }
            }
            //賦值給bean
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }
        //若是未創(chuàng)建的虑省,則進入下面的邏輯
        else {
            // 正在創(chuàng)建此 beanName 的 prototype 類型的 bean探颈,那么拋異常伪节,這往往是因為陷入了循環(huán)引用
            if (isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }

            // 檢查工廠中是否存在beanDefinition
            BeanFactory parentBeanFactory = getParentBeanFactory();
            //若當前工廠沒有怀大,檢查父工廠
            if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
                String nameToLookup = originalBeanName(name);
                //父工廠為AbstractBeanFactory實例潜慎,讓父工廠返回bean
                if (parentBeanFactory instanceof AbstractBeanFactory) {
                    return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                            nameToLookup, requiredType, args, typeCheckOnly);
                }
                //父工廠不是AbstractBeanFactory實例铐炫,且args不為空
                else if (args != null) {
                    // 傳入args讓父工廠代理產生bean
                    return (T) parentBeanFactory.getBean(nameToLookup, args);
                }
                //兩個條件都不滿足,代理到普通的getBean方法
                else {
                    return parentBeanFactory.getBean(nameToLookup, requiredType);
                }
            }
            //typeCheckOnly是傳參為false山涡,這里會進入到if語句中
            if (!typeCheckOnly) {
                //標記當前bean已經被創(chuàng)建
                markBeanAsCreated(beanName);
            }
            
            //如果不需要父工廠處理竞穷,當前工廠就自己處理
            try {
                //獲取bean定義瘾带,由于bean中很可能有依賴項看政,所以管他叫MergedLocalBeanDefinition
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                //檢查是否為abstract,很簡單不展開
                checkMergedBeanDefinition(mbd, beanName, args);

                // 獲取當前bean所依賴的bean
                String[] dependsOn = mbd.getDependsOn();
                if (dependsOn != null) {
                    for (String dep : dependsOn) {
                        if (isDependent(beanName, dep)) {
                            //循環(huán)引用拋出異常
                            ...... 
                        }
                        //注冊依賴關系嚷兔,后面會展開冒晰,可以先往下看
                        registerDependentBean(dep, beanName);
                        try {
                            //初始化該依賴
                            getBean(dep);
                        }
                        catch (NoSuchBeanDefinitionException ex) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                        }
                    }
                }

                // 當bean屬于普通單例,則初始化該單例
                if (mbd.isSingleton()) {
                    sharedInstance = getSingleton(beanName, () -> {
                        //這里創(chuàng)建了Bean蒋情,很重要恕出,之后展開
                        try {
                            return createBean(beanName, mbd, args);
                        }
                        catch (BeansException ex) {
                            // 刪除緩存中的Bean
                            // 同時刪除所有接收了當前Bean的臨時引用的Bean
                            destroySingleton(beanName);
                            //拋出異常
                            throw ex;
                        }
                    });
                    //若創(chuàng)建Bean成功浙巫,則為bean賦值的畴,前面講到bean用來作為返回值
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }
                //如果bean屬于prototype
                else if (mbd.isPrototype()) {
                    // It's a prototype -> create a new instance.
                    Object prototypeInstance = null;
                    try {
                        //在創(chuàng)建bean之前的操作,比較簡單煎娇,不展開
                        beforePrototypeCreation(beanName);
                        //創(chuàng)建bean
                        prototypeInstance = createBean(beanName, mbd, args);
                    }
                    finally {
                        //和boefore操作差不都缓呛,也不展開
                        afterPrototypeCreation(beanName);
                    }
                    bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                }
                //bean屬于其他域,操作和前面差不多痰憎,這塊就省略了
                else {
                    ......
                }
            }
            catch (BeansException ex) {
                //若bean產生失敗票髓,則進行清理,并拋出異常铣耘,較簡單洽沟,就是在表示已創(chuàng)建bean的Set集合中將當前beanName移除
                cleanupAfterBeanCreationFailure(beanName);
                throw ex;
            }
        }

        // requiredType是要檢索的bean的所需類型,若不為空蜗细,且類型匹配玲躯,則進行類型轉換
        if (requiredType != null && !requiredType.isInstance(bean)) {
            try {
                T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
                if (convertedBean == null) {
                    throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
                }
                return convertedBean;
            }
            catch (TypeMismatchException ex) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Failed to convert bean '" + name + "' to required type '" +
                            ClassUtils.getQualifiedName(requiredType) + "'", ex);
                }
                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
            }
        }
    //返回Bean
        return (T) bean;
}

值得一提的是spring加載bean的方式其實很有趣,當子容器在當前beanDefinitionMap中找不到beanDefinition時就會把任務丟給父容器去做鳄乏,如果父容器找不到跷车,還會丟給他的父容器去找密强,實在是有點坑爹的嫌疑,但其實這個遞歸的調用卻又很巧妙,每個容器只要做好自己分內的事即可地熄,將不屬于自己的任務向上拋出却特,層層向上處理轰绵,真是妙哉液样。下面是getBean方法中一些重要的相關操作澎怒,可以對著上面的代碼找到對應的實現

六琳状、registerDependentBean(dep, beanName)

在初始化一個bean時肮柜,需要將bean內的依賴與當前bean注冊一個依賴關系待讳,來看看spring為什么要注冊依賴關系,并且是怎么做的涂邀。在下面的代碼中找到dependentBeanMapdependenciesForBeanMap观蜗,這是注冊關系的關鍵岸售。

找到兩者在源碼中的對應位置,看看他們是什么樣的

dependentBeanMap

/** Map between dependent bean names: bean name --> Set of dependent bean names */
    private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64);

這里存儲的是被依賴者與依賴者的關系,比如User中有一項依賴叫Car复哆,那么dependentBeanMap存儲的就是carName:userName

dependenciesForBeanMap

/** Map between depending bean names: bean name --> Set of bean names for the bean's dependencies */
private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<>(64);

這里就是和上面的反一反久免,userName:carName

現在就來看看代碼把~

/**
     * Register a dependent bean for the given bean,
     * to be destroyed before the given bean is destroyed.
     * @param beanName the name of the bean
     * @param dependentBeanName the name of the dependent bean
     */
public void registerDependentBean(String beanName, String dependentBeanName) {
        String canonicalName = canonicalName(beanName);

        synchronized (this.dependentBeanMap) {
            //若被依賴項的依賴關系不存在,則創(chuàng)建一個
            Set<String> dependentBeans =
        this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8));
            //添加依賴關系丁寄,若beanName:dependentBeanName已存在,則return
            if (!dependentBeans.add(dependentBeanName)) {
                return;
            }
        }

        synchronized (this.dependenciesForBeanMap) {
            //若被依賴項的依賴關系不存在豪筝,則創(chuàng)建一個
            Set<String> dependenciesForBean =
this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8));
            //添加依賴關系
            dependenciesForBean.add(canonicalName);
        }
}

其實可以從方法上的注釋即可知道:“to be destroyed before the given bean is destroyed”峻黍,即“被依賴項會在給定的bean被銷毀之前被銷毀”仑扑,spring這么做的目的就很清晰了——為了GC蛛碌。

再來討論一下里面的這一句:

//添加依賴關系,若beanName:dependentBeanName已存在辖源,則return
if (!dependentBeans.add(dependentBeanName)) {
    return;
}

為什么如果被依賴項與依賴項的關系已建立蔚携,就不用再建立依賴項與被依賴項的關系?……這聽起來很拗口克饶,但確實是這么回事兒酝蜒。想知道答案可以去同一個類中registerContainedBean方法去看看就能明白啦~好了,現在回到繼續(xù)看后面的代碼把

七矾湃、createBean(beanName, mbd, args)

第三個參數 args 數組代表創(chuàng)建實例需要的參數亡脑,就是給構造方法用的參數,或者是工廠 Bean 的參數。不過要注意的是在初始化階段霉咨,args 是 null蛙紫。create Bean的實現在AbstractAutowireCapableBeanFactory類中

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
            throws BeanCreationException {

        ......
        RootBeanDefinition mbdToUse = mbd;

        // 確保 BeanDefinition 中的 Class 被加載
        // 同時在動態(tài)解析類的情況下克隆bean定義提供使用,這個bean定義不能被存儲在mbd中
        Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
        if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
            mbdToUse = new RootBeanDefinition(mbd);
            mbdToUse.setBeanClass(resolvedClass);
        }

        // 準備當前bean的lookupMethod和replacedMathoed等途戒,可以參考https://www.cnblogs.com/ViviChan/p/4981619.html
        try {
            mbdToUse.prepareMethodOverrides();
        }
        catch (BeanDefinitionValidationException ex) {
            //拋出異常
            ......
        }
        try {
            // 使BeanPostProcessors有機會返回一個代理bean
            Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
            if (bean != null) {
                return bean;
            }
        }
        catch (Throwable ex) {
            //拋出異常
            ......
        }
        try {
            //doCreateBean才是關鍵惊来,后面會展開
            Object beanInstance = doCreateBean(beanName, mbdToUse, args);
            //拋出異常
            ......
            }
            return beanInstance;
        }
        catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
            //拋出異常
            ......
        }
        catch (Throwable ex) {
            //拋出異常
            ......
        }
}

八、doCreateBean(beanName, mbdToUse, args)

又是一長串代碼棺滞,真的難頂了裁蚁,不過我想spring這么做也是有他的苦衷的,給人家一個面子繼續(xù)看下去吧继准。

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
            throws BeanCreationException {

        // BeanWrrapper枉证,Bean包裝器,簡單理解成對bean賦值的移必,后面展開
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            //若mbd為單例室谚,需要先判斷是否為FactoryBean
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        //如果instanceWrapper為空,則創(chuàng)建一個bean實例
        if (instanceWrapper == null) {
            //createBeanInstance崔泵,創(chuàng)建bean實例封裝到wrapper中秒赤,后面展開
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        //通過wrapper獲取到了bean
        final Object bean = instanceWrapper.getWrappedInstance();
        //處理bean類型
        Class<?> beanType = instanceWrapper.getWrappedClass();
        if (beanType != NullBean.class) {
            mbd.resolvedTargetType = beanType;
        }
        // 允許post-processors修改mbd
        synchronized (mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                try {
                 //簡單來說就是對mbd做一些加工  
                 applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                }
                catch (Throwable ex) {
                    //拋出異常
                    ......
                }
                mbd.postProcessed = true;
            }
        }
        // 解決循環(huán)依賴的問題
        boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                isSingletonCurrentlyInCreation(beanName));
        if (earlySingletonExposure) {
            ......
            addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
        }
        // bean在實例化后,還需要賦值和初始化(init)
        Object exposedObject = bean;
        try {
            //這一步負責屬性裝配憎瘸,關鍵就在于BeanWrapper
            populateBean(beanName, mbd, instanceWrapper);
            //處理 bean 初始化完成后的各種回調
            exposedObject = initializeBean(beanName, exposedObject, mbd);
        }
        catch (Throwable ex) {
            //拋出異常
            ......
        }
        //主要用于解決循環(huán)引用入篮,這部分先跳過吧
        if (earlySingletonExposure) {
            Object earlySingletonReference = getSingleton(beanName, false);
            if (earlySingletonReference != null) {
                if (exposedObject == bean) {
                    exposedObject = earlySingletonReference;
                }
                else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                    String[] dependentBeans = getDependentBeans(beanName);
                    Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
                    for (String dependentBean : dependentBeans) {
                        if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                            actualDependentBeans.add(dependentBean);
                        }
                    }
                    if (!actualDependentBeans.isEmpty()) {
                        //拋出異常
                        ......
                    }
                }
            }
        }
        // 注冊bean為使用后即銷毀
        try {
            registerDisposableBeanIfNecessary(beanName, bean, mbd);
        }
        catch (BeanDefinitionValidationException ex) {
            //拋出異常
            ......
        }
        return exposedObject;
}

doCreateBean方法真是細節(jié)拉滿,分別來看看以下關鍵的幾步

1.BeanWrapper

可以發(fā)現createBeanInstance方法雖然創(chuàng)建了bean實例幌甘,但是返回的其實是一個BeanWrapper潮售,他到底是個什么東西?

其實BeanWrapper相當于一個容器锅风,Spring委托BeanWrapperwancehngBean屬性的填充工作酥诽。在Bean實例被創(chuàng)建出來之后,容器主控程序將Bean實例通過BeanWrapper包裝起來皱埠,這是通過調用BeanWrapper的setWrappedInstance方法完成的肮帐。

2.createBeanInstance(beanName, mbd, args)

這里是創(chuàng)建bean實例的關鍵,由于考慮后續(xù)代碼依舊有一大把边器,我的心態(tài)實在受到了影響训枢,就放到下一次討論吧……

3.populateBean(beanName, mbd, instanceWrapper)

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
   //若beanwrapper為空,則需要判斷是否需要為bean賦值
   if (bw == null) {
      //有屬性且wrapper為空饰抒,則會拋出異常肮砾,原因不言而喻
      if (mbd.hasPropertyValues()) {
         throw new BeanCreationException(
               mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
      }
      //沒有屬性,那就不需要賦值啦袋坑!直接返回
      else {
         return;
      }
   }

   // 到這步的時候仗处,bean 實例化完成(通過工廠方法或構造方法)眯勾,但是還沒開始屬性設值,InstantiationAwareBeanPostProcessor 的實現類可以在這里對 bean進行狀態(tài)修改
   boolean continueWithPropertyPopulation = true;

   if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
      for (BeanPostProcessor bp : getBeanPostProcessors()) {
         if (bp instanceof InstantiationAwareBeanPostProcessor) {
            InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
            // 如果返回 false婆誓,代表不需要進行后續(xù)的屬性設值吃环,也不需要再經過其他的 BeanPostProcessor 的處理
            if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
               continueWithPropertyPopulation = false;
               break;
            }
         }
      }
   }
   //若不需要再賦值,則return
   if (!continueWithPropertyPopulation) {
      return;
   }
   //獲取propertyValues
   PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

   if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
         mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
      MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
      //下面的代碼能知道干了啥就行洋幻,不是(就是)因為我實力不夠郁轻,謝謝
      // 通過名字找到所有屬性值,如果是 bean 依賴文留,先初始化依賴的 bean好唯。記錄依賴關系
      if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
         autowireByName(beanName, mbd, bw, newPvs);
      }
      // 通過類型裝配
      if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
         autowireByType(beanName, mbd, bw, newPvs);
      }
      pvs = newPvs;
   }
   //是否包含InstantiationAwareBeanPostProcessors
   boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
   //是否需要深度檢查
   boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);

   if (hasInstAwareBpps || needsDepCheck) {
      if (pvs == null) {
         pvs = mbd.getPropertyValues();
      }
      PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
      if (hasInstAwareBpps) {
         for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof InstantiationAwareBeanPostProcessor) {
               InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
               //使用postProcessor對propertyValues進行處理
               pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
               if (pvs == null) {
                  return;
               }
            }
         }
      }
      if (needsDepCheck) {
         //檢查依賴
         checkDependencies(beanName, mbd, filteredPds, pvs);
      }
   }

   if (pvs != null) {
      // 設置 bean 實例的屬性值,這里就不展開了燥翅,到此骑篙,bean實例的賦值就完成了
      applyPropertyValues(beanName, mbd, bw, pvs);
   }
}

九、結論

寫了這么多森书,bean實例的創(chuàng)建還是要被移到后面了靶端,不過這次的收獲也不小,從refresh加載單例bean其實可以窺見spring是如何加載所有bean的凛膏,其中也包括了一些postProcessor的實際應用等等杨名。由于代碼真的很多,所以覺得還是需要花時間消化消化的猖毫。

希望后續(xù)的代碼能善待我吧台谍,阿門!

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末鄙麦,一起剝皮案震驚了整個濱河市典唇,隨后出現的幾起案子镊折,更是在濱河造成了極大的恐慌胯府,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件恨胚,死亡現場離奇詭異骂因,居然都是意外死亡,警方通過查閱死者的電腦和手機赃泡,發(fā)現死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門寒波,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人升熊,你說我怎么就攤上這事俄烁。” “怎么了级野?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵页屠,是天一觀的道長。 經常有香客問我,道長辰企,這世上最難降的妖魔是什么风纠? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮牢贸,結果婚禮上竹观,老公的妹妹穿的比我還像新娘。我一直安慰自己潜索,他們只是感情好臭增,可當我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著竹习,像睡著了一般速址。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上由驹,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天芍锚,我揣著相機與錄音,去河邊找鬼蔓榄。 笑死并炮,一個胖子當著我的面吹牛,可吹牛的內容都是我干的甥郑。 我是一名探鬼主播逃魄,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼澜搅!你這毒婦竟也來了伍俘?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤勉躺,失蹤者是張志新(化名)和其女友劉穎癌瘾,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體饵溅,經...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡妨退,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了蜕企。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片咬荷。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖轻掩,靈堂內的尸體忽然破棺而出幸乒,到底是詐尸還是另有隱情,我是刑警寧澤唇牧,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布罕扎,位于F島的核電站基茵,受9級特大地震影響,放射性物質發(fā)生泄漏壳影。R本人自食惡果不足惜拱层,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望宴咧。 院中可真熱鬧根灯,春花似錦、人聲如沸掺栅。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽氧卧。三九已至桃笙,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間沙绝,已是汗流浹背搏明。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留闪檬,地道東北人星著。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像粗悯,于是被迫代替她去往敵國和親虚循。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,033評論 2 355