Bean到底是咋生下來的?

老子終于更新了曲伊,哈哈哈哈
上回書咱們說道叽讳,bean的生成全靠BeanDefinition,但是BeanDefinition里面僅僅只有bean的結(jié)構(gòu)內(nèi)容坟募,而它還要經(jīng)過一系列的組裝岛蚤,再最終完成后可能跟當(dāng)初定義的bean大相徑庭,就好比我和思聰在上帝那都定義為人懈糯,但是出生的時(shí)候....默默流下了淚水涤妒。這里,我們就圍繞著bean在生產(chǎn)過程中遇到的一些事件(比實(shí)例化前后處理器等)來展開剖析赚哗。

一. doGetBean

doGetBean是在AbstractBeanFactory容器中定義的方法她紫,我們就拿他來開刀。

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

        // 這里主要是處理別名或者FactoryBean的名字
        final String beanName = transformedBeanName(name);
        Object bean;

        // 先從三級(jí)緩存中嘗試獲取bean蜂奸,詳情見下文
        Object sharedInstance = getSingleton(beanName);
        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 + "'");
                }
            }
            // 這個(gè)主要對FactoryBean做處理犁苏,如果sharedInstance 是一個(gè)FactoryBean,那它將返回FactoryBean中所創(chuàng)建的實(shí)例
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }

        else {

            if (isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }

            //先委托給父BeanFactory去看看能否創(chuàng)建出實(shí)例
            BeanFactory parentBeanFactory = getParentBeanFactory();
            if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
                String nameToLookup = originalBeanName(name);
                if (parentBeanFactory instanceof AbstractBeanFactory) {
                    return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                            nameToLookup, requiredType, args, typeCheckOnly);
                }
                else if (args != null) {
                    return (T) parentBeanFactory.getBean(nameToLookup, args);
                }
                else if (requiredType != null) {
                    return parentBeanFactory.getBean(nameToLookup, requiredType);
                }
                else {
                    return (T) parentBeanFactory.getBean(nameToLookup);
                }
            }

            //標(biāo)記Bean為正在創(chuàng)建中的一個(gè)狀態(tài)
            if (!typeCheckOnly) {
                markBeanAsCreated(beanName);
            }

            try {
                //如果此bean對應(yīng)的BeanDefinition有雙親扩所,則需要合并BeanDefinition中的內(nèi)容
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                checkMergedBeanDefinition(mbd, beanName, args);

                // 這里獲取XML中顯示指定的depends-on的依賴围详,并遞歸獲取這些依賴Bean的實(shí)例
                String[] dependsOn = mbd.getDependsOn();
                if (dependsOn != null) {
                    for (String dep : dependsOn) {
                        if (isDependent(beanName, dep)) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                        }
                        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()) {
                    // addSingleton里面調(diào)用的核心是createBean,在createBean方法創(chuàng)建完bean之后會(huì)把bean加入一級(jí)緩存并刪除二三級(jí)的緩存
                    sharedInstance = getSingleton(beanName, () -> {
                        try {
                            return createBean(beanName, mbd, args);
                        }
                        catch (BeansException ex) {
                            destroySingleton(beanName);
                            throw ex;
                        }
                    });
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }

                //忽略部分代碼
                .....

                }
            }
            catch (BeansException ex) {
                cleanupAfterBeanCreationFailure(beanName);
                throw ex;
            }
        }

        //忽略部分代碼
        .....

        return (T) bean;
    }
  • getSingleton

singletonObject : 第一級(jí)緩存祖屏,存放完整的Bean
earlySingletonObjects: 第二級(jí)緩存助赞,存放不完整的Bean
singletonFactories: 第三級(jí)緩存,存放Bean工廠
singletonObject 是一個(gè) ConcurrentHashMap袁勺,而earlySingletonObjects和singletonFactories是一個(gè)HashMap雹食,看下這個(gè)方法的實(shí)現(xiàn)就知道為啥。

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        //肯定要先看看一級(jí)緩存在不在
        Object singletonObject = this.singletonObjects.get(beanName);
        //該Bean不存在或者還在創(chuàng)建中
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            synchronized (this.singletonObjects) {
                //從二級(jí)緩存中取
                singletonObject = this.earlySingletonObjects.get(beanName);
                if (singletonObject == null && allowEarlyReference) {
                    //從三級(jí)緩存中取
                    ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                    if (singletonFactory != null) {
                        //如果從Bean工廠中拿到bean則存入二級(jí)緩存并刪除三級(jí)緩存
                        singletonObject = singletonFactory.getObject();
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }
        return singletonObject;
    }

二. createBean

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

        if (logger.isTraceEnabled()) {
            logger.trace("Creating instance of bean '" + beanName + "'");
        }
        RootBeanDefinition mbdToUse = mbd;

        // 這里主要是加載bean的Class
        Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
        if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
            mbdToUse = new RootBeanDefinition(mbd);
            mbdToUse.setBeanClass(resolvedClass);
        }

        // 這里準(zhǔn)備需要重寫的方法期丰,注意這里不是@override標(biāo)記的方法群叶,而是在XML中顯示指明要替換的方法,
        try {
            mbdToUse.prepareMethodOverrides();
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
                    beanName, "Validation of method overrides failed", ex);
        }

        try {
            //這里就精髓了钝荡,如果用戶自定義了bean的生成方式街立,則直接return,返回不會(huì)讓doCreateBean方法執(zhí)行埠通,詳情看下文
            Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
            if (bean != null) {
                return bean;
            }
        }
        catch (Throwable ex) {
            throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
                    "BeanPostProcessor before instantiation of bean failed", ex);
        }

        try {
            //這里是bean生成的核心具篇,詳情看下文
            Object beanInstance = doCreateBean(beanName, mbdToUse, args);
            if (logger.isTraceEnabled()) {
                logger.trace("Finished creating instance of bean '" + beanName + "'");
            }
            return beanInstance;
        }
        catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {

            throw ex;
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
        }
    }
  • resolveBeforeInstantiation

在bean生成的時(shí)候略步,Spring會(huì)加載很多BeanPostProcessors來對bean的生成過程做一個(gè)增強(qiáng)。
而InstantiationAwareBeanPostProcessor是眾多BeanPostProcessor子類的其中之一芹务,它里面有5個(gè)關(guān)鍵的方法:

postProcessBeforeInstantiation:Bean實(shí)例化的前置方法
postProcessAfterInstantiation:Bean實(shí)例化的后置方法
postProcessBeforeInitialization:Bean初始化的前置方法
postProcessAfterInitialization:Bean初始化的后置方法
postProcessProperties:輔助依賴注入

applyBeanPostProcessorsBeforeInstantiation的目的就是執(zhí)行Bean實(shí)例化的前置方法。假如Bean實(shí)例化的前置方法中生成了用戶自定義的Bean,那就會(huì)直接執(zhí)行Bean初始化的后置方法,之后將生成的Bean直接返回給用戶,而不交由spring的doCreateBean來創(chuàng)建Bean码撰。

    protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
        Object bean = null;
        if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
            if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
                Class<?> targetType = determineTargetType(beanName, mbd);
                if (targetType != null) {
                    bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                    if (bean != null) {
                        bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
                    }
                }
            }
            mbd.beforeInstantiationResolved = (bean != null);
        }
        return bean;
    }

二.doCreateBean

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

        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            //嘗試從緩存中獲取factoryBean(就當(dāng)是我們將要獲取的bean的包裝bean實(shí)例)
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        if (instanceWrapper == null) {
            //嘗試使用工廠方法、有參構(gòu)造函數(shù)众雷、無參構(gòu)造函數(shù)去實(shí)例化一個(gè)bean
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        final Object bean = instanceWrapper.getWrappedInstance();
        Class<?> beanType = instanceWrapper.getWrappedClass();
        if (beanType != NullBean.class) {
            mbd.resolvedTargetType = beanType;
        }

        synchronized (mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                try {
                    //這里是為依賴注入做準(zhǔn)備灸拍,主要是AutowiredAnnotationBeanPostProcessor起作用
                    //這個(gè)PostProcessor會(huì)解析@autowired和@value注解并把標(biāo)記的屬性封裝成InjectionMetadata元數(shù)據(jù)加入緩存,
                    //之后在populateBean中會(huì)調(diào)用此PostProcessor實(shí)例化后置方法并根據(jù)這些元數(shù)據(jù)去進(jìn)行屬性注入
                    applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                }
                catch (Throwable ex) {
                    throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                            "Post-processing of merged bean definition failed", ex);
                }
                mbd.postProcessed = true;
            }
        }

        
        boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                isSingletonCurrentlyInCreation(beanName));
        if (earlySingletonExposure) {
            if (logger.isTraceEnabled()) {
                logger.trace("Eagerly caching bean '" + beanName +
                        "' to allow for resolving potential circular references");
            }
            // addSingletonFactory就是將bean加入第三級(jí)緩存
            // getEarlyBeanReference的實(shí)現(xiàn)是在AbstractAutoProxyCreator這個(gè)類里面砾省,里面是實(shí)現(xiàn)AOP和創(chuàng)建代理對象的核心
            addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
        }

        Object exposedObject = bean;
        try {
            // 屬性注入的核心方法鸡岗,下文會(huì)講到
            populateBean(beanName, mbd, instanceWrapper);
            // 1.處理繼承了BeanNameAware、BeanClassLoaderAware编兄、BeanFactoryAware接口的bean并注入這些值
            // 2.執(zhí)bean初始化前置方法
            // 3.執(zhí)bean初始化方法
            // 4.執(zhí)bean初始化后置方法
            exposedObject = initializeBean(beanName, exposedObject, mbd);
        }
        //忽略部分代碼
        .....

        
    }
  • populateBean
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
        //忽略部分代碼
        .....

        // 這里是執(zhí)行實(shí)例化的后置方法轩性,這個(gè)方法返回值為boolean,可以控制能否繼續(xù)執(zhí)行后面有關(guān)依賴注入的代碼
        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                    if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                        return;
                    }
                }
            }
        }

        PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

        //這里是處理xml中某些Bean顯示指定BY_NAME或BY_TYPE的方式來注入
        int resolvedAutowireMode = mbd.getResolvedAutowireMode();
        if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
            MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
            if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
                autowireByName(beanName, mbd, bw, newPvs);
            }
            if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
                autowireByType(beanName, mbd, bw, newPvs);
            }
            pvs = newPvs;
        }

        boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
        boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

        //下面這一塊就是注入的核心流程了狠鸳,主要還是依賴于AutowiredAnnotationBeanPostProcessor,會(huì)在Bean列表中找出最符合的bean注入件舵,這個(gè)有時(shí)間再細(xì)細(xì)擼
        PropertyDescriptor[] filteredPds = null;
        if (hasInstAwareBpps) {
            if (pvs == null) {
                pvs = mbd.getPropertyValues();
            }
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                    PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
                    if (pvsToUse == null) {
                        if (filteredPds == null) {
                            filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                        }
                        pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                        if (pvsToUse == null) {
                            return;
                        }
                    }
                    pvs = pvsToUse;
                }
            }
        }
        if (needsDepCheck) {
            if (filteredPds == null) {
                filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
            }
            checkDependencies(beanName, mbd, filteredPds, pvs);
        }

        if (pvs != null) {
            applyPropertyValues(beanName, mbd, bw, pvs);
        }
    }

總結(jié)

按順序來描述一下bean生成經(jīng)歷的一些過程(縮進(jìn)太多我直接貼圖了)

image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末卸察,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子铅祸,更是在濱河造成了極大的恐慌坑质,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,858評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件临梗,死亡現(xiàn)場離奇詭異涡扼,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)盟庞,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門吃沪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人什猖,你說我怎么就攤上這事票彪。” “怎么了不狮?”我有些...
    開封第一講書人閱讀 165,282評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵降铸,是天一觀的道長。 經(jīng)常有香客問我荤傲,道長,這世上最難降的妖魔是什么颈渊? 我笑而不...
    開封第一講書人閱讀 58,842評(píng)論 1 295
  • 正文 為了忘掉前任遂黍,我火速辦了婚禮终佛,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘雾家。我一直安慰自己铃彰,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評(píng)論 6 392
  • 文/花漫 我一把揭開白布芯咧。 她就那樣靜靜地躺著牙捉,像睡著了一般。 火紅的嫁衣襯著肌膚如雪敬飒。 梳的紋絲不亂的頭發(fā)上邪铲,一...
    開封第一講書人閱讀 51,679評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音无拗,去河邊找鬼带到。 笑死,一個(gè)胖子當(dāng)著我的面吹牛英染,可吹牛的內(nèi)容都是我干的揽惹。 我是一名探鬼主播,決...
    沈念sama閱讀 40,406評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼四康,長吁一口氣:“原來是場噩夢啊……” “哼搪搏!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起闪金,我...
    開封第一講書人閱讀 39,311評(píng)論 0 276
  • 序言:老撾萬榮一對情侶失蹤疯溺,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后毕泌,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體喝检,經(jīng)...
    沈念sama閱讀 45,767評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年撼泛,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了挠说。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,090評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡愿题,死狀恐怖损俭,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情潘酗,我是刑警寧澤杆兵,帶...
    沈念sama閱讀 35,785評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站仔夺,受9級(jí)特大地震影響琐脏,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評(píng)論 3 331
  • 文/蒙蒙 一日裙、第九天 我趴在偏房一處隱蔽的房頂上張望吹艇。 院中可真熱鬧,春花似錦昂拂、人聲如沸受神。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽鼻听。三九已至,卻和暖如春联四,著一層夾襖步出監(jiān)牢的瞬間撑碴,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評(píng)論 1 271
  • 我被黑心中介騙來泰國打工碎连, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留灰羽,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,298評(píng)論 3 372
  • 正文 我出身青樓鱼辙,卻偏偏與公主長得像廉嚼,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子倒戏,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評(píng)論 2 355