Spring源碼(五)-bean的加載(下)

前言

接的私活有點(diǎn)趕進(jìn)度,加上周四搬工位,昨天看了演唱會(huì),加上改bug一直沒有抽出時(shí)間來寫,今天估計(jì)補(bǔ)不上周四的了,周末也有事情,周四的下周一定不上。廢話不說了,我們繼續(xù)之前bean的加載下篇,bean的加載是spirng-ioc的核心,我自己理解的也不是特別好,有感興趣的小伙伴歡迎一起聊聊。
QQ:616516146,Gmail:liangliang1259@gmail.com

1、getBean()

這個(gè)方法有點(diǎn)長我們進(jìn)行分段解析。

1.1、從緩存獲取

//提取對(duì)應(yīng)的beanName
final String beanName = transformedBeanName(name);
Object bean;

// Eagerly check singleton cache for manually registered singletons.
/**
 * 檢查緩存中或者實(shí)例工廠中是否有對(duì)應(yīng)實(shí)例
 * 為何會(huì)首先使用這段代碼
 * 因?yàn)樵趧?chuàng)建單例bean的時(shí)候會(huì)存在依賴注入的情況,而在創(chuàng)建依賴的時(shí)候?yàn)榱吮苊庋h(huán)依賴
 * Spring創(chuàng)建Bean的原則是不等bean創(chuàng)建完成就會(huì)將創(chuàng)建Bean的ObjectFactory提早曝光
 * 也就是講ObjectFactory加入到緩存中,一旦下一個(gè)bean創(chuàng)建的時(shí)候需要依賴上個(gè)bean則直接使用ObjectFactory
 */
//嘗試從混成或者singletonFactories中的ObjectFactory中獲取
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 + "'");
        }
    }

    bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}


這個(gè)方法首先從緩存中去獲取,這個(gè)時(shí)候緩存中當(dāng)然沒有數(shù)據(jù),因?yàn)榇藭r(shí)是初始化,我們還沒有將bean方到singletonObjects這個(gè)map中去,如下圖代碼。

1.1.1、getSingleton()
    @Nullable
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        //檢查緩存中是否存在實(shí)例
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            //若不存在則鎖定全局變量進(jìn)行處理
            synchronized (this.singletonObjects) {
                singletonObject = this.earlySingletonObjects.get(beanName);
                if (singletonObject == null && allowEarlyReference) {
                    ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                    if (singletonFactory != null) {
                        //調(diào)用預(yù)先設(shè)定的getObject方法
                        singletonObject = singletonFactory.getObject();
                        //記錄在緩存中,earlySingletonObjects和singletonFactories互斥
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }
        return (singletonObject != NULL_OBJECT ? singletonObject : null);
    }

1.2、獲取beanFacotry

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

// Check if bean definition exists in this factory.
//如果beaDefinitionMap中也就是在所有已經(jīng)加載的類中不包括beanName則嘗試從parentBeanFactory中檢測(cè)
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
    // Not found -> check parent.
    String nameToLookup = originalBeanName(name);
    if (parentBeanFactory instanceof AbstractBeanFactory) {
        return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                nameToLookup, requiredType, args, typeCheckOnly);
    }
    else if (args != null) {
        //遞歸到BeanFactory中去尋找
        // Delegation to parent with explicit args.
        return (T) parentBeanFactory.getBean(nameToLookup, args);
    }
    else {
        // No args -> delegate to standard getBean method.
        return parentBeanFactory.getBean(nameToLookup, requiredType);
    }
}

這段代碼首先獲取該bean的父類,若有父類則用父類去實(shí)例化該bean,這里的parentBeanFactory為null,暫時(shí)不做考慮。接下來看第三部分。

1.3

//如果不是做類型檢查則是創(chuàng)建bean,這里要進(jìn)行記錄
//第一部分
if (!typeCheckOnly) {
    markBeanAsCreated(beanName);
}
//第二部分
try {
    final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
    checkMergedBeanDefinition(mbd, beanName, args);

    // Guarantee initialization of beans that the current bean depends on.
    String[] dependsOn = mbd.getDependsOn();
    //若存在依賴則需要遞歸實(shí)例化依賴的bean
    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);
            getBean(dep);
        }
    }
//第三部分
    // Create bean instance.
    //實(shí)例化依賴的bean之后可以實(shí)例化mbd本身了
    //單例模式的創(chuàng)建
    if (mbd.isSingleton()) {
        sharedInstance = getSingleton(beanName, () -> {
            try {
                /**
                 *核心創(chuàng)建bean
                 */
                return createBean(beanName, mbd, args);
            }
            catch (BeansException ex) {
                // Explicitly remove instance from singleton cache: It might have been put there
                // eagerly by the creation process, to allow for circular reference resolution.
                // Also remove any beans that received a temporary reference to the bean.
                destroySingleton(beanName);
                throw ex;
            }
        });
        //真正的bean初始化處理
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
    }

  • 1、第一部分,標(biāo)記目前的bean屬于正在創(chuàng)建狀態(tài)
  • 2、第二部分,根據(jù)beanName獲取該bean在beanFactory中的beanDefinitionMap中beanDefinition,然后獲取該bean所依賴的bean(此處是spring解決循環(huán)依賴的關(guān)鍵),如果依賴的bean還未創(chuàng)建,則先創(chuàng)建依賴的bean,依次遞歸調(diào)用(DI依賴注入的概念),如果找不到依賴,則忽略。
  • 3、若是單例,創(chuàng)建bean,調(diào)用CreateBean()方法,此處只考慮單例模式

接下來跟蹤createBean()方法。此處調(diào)用的是AbstractAutowireCapableBeanFactory中的方法

1.4、createBean()

//第一部分
if (logger.isDebugEnabled()) {
    logger.debug("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;

// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
/**
 * 鎖定class,根據(jù)設(shè)置的class屬性或者根據(jù)classname來解析class
 */
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
    mbdToUse = new RootBeanDefinition(mbd);
    mbdToUse.setBeanClass(resolvedClass);
}
//第二部分
//驗(yàn)證及準(zhǔn)備覆蓋的方法
try {
    mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
    throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
            beanName, "Validation of method overrides failed", ex);
}
//第三部分
try {
    // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
    //給BeanPostProcessors一個(gè)機(jī)會(huì)來返回代理來代替真正的實(shí)例,前置處理器
    Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
    /**
     * 前置處理后返回結(jié)果不為空,直接返回結(jié)果,AOP功能就是基于這里判斷的
     */
    if (bean != null) {
        return bean;
    }
}
catch (Throwable ex) {
    throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
            "BeanPostProcessor before instantiation of bean failed", ex);
}
//第四部分
try {
    Object beanInstance = doCreateBean(beanName, mbdToUse, args);
    if (logger.isDebugEnabled()) {
        logger.debug("Finished creating instance of bean '" + beanName + "'");
    }
    return beanInstance;
}

  • 1、第一部分:確保該bean的class是真實(shí)存在的,也就是該bean是可以classload可以找到加載的,若不存在則放入beanDefination中
  • 2、第二部分:準(zhǔn)備方法的重寫
  • 3、第三部分:(重要)最后的return就是返回的bean,但看注釋:Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.這邊就很清晰了,我們以前在beanPostProcessor的章節(jié)講過,beanPostProcessor是可以臨時(shí)修改bean的,它的優(yōu)先級(jí)高于正常實(shí)例化bean的(也就是第四部分實(shí)例化的方法)如果beanPostProcessor能返回,則直接返回了,這邊代碼下次分析,我們還是先分析主要流程:
  • 4、doCreateBean(beanName, mbd, args)這個(gè)方法,接下來看這個(gè)
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        if (instanceWrapper == null) {
            //根據(jù)指定的bean使用對(duì)應(yīng)的側(cè)臉創(chuàng)建新的實(shí)例,如工廠方法,構(gòu)造函數(shù)自動(dòng)注入,簡單初始化
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
        Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
        mbd.resolvedTargetType = beanType;

        if (beanType != null) {
            // Allow post-processors to modify the merged bean definition.
            synchronized (mbd.postProcessingLock) {
                if (!mbd.postProcessed) {
                    try {
                        applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                    }
                    catch (Throwable ex) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                "Post-processing of merged bean definition failed", ex);
                    }
                    mbd.postProcessed = true;
                }
            }
        }

這里首先初始化一個(gè)instanceWrapper,然后再看createBeanInstance()

    protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
        // Make sure bean class is actually resolved at this point.
        Class<?> beanClass = resolveBeanClass(mbd, beanName);

        if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                    "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
        }

        Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
        if (instanceSupplier != null) {
            return obtainFromSupplier(instanceSupplier, beanName);
        }

        if (mbd.getFactoryMethodName() != null)  {
            return instantiateUsingFactoryMethod(beanName, mbd, args);
        }

        // Shortcut when re-creating the same bean...
        boolean resolved = false;
        boolean autowireNecessary = false;
        if (args == null) {
            synchronized (mbd.constructorArgumentLock) {
                if (mbd.resolvedConstructorOrFactoryMethod != null) {
                    resolved = true;
                    autowireNecessary = mbd.constructorArgumentsResolved;
                }
            }
        }
        if (resolved) {
            if (autowireNecessary) {
                return autowireConstructor(beanName, mbd, null, null);
            }
            else {
                return instantiateBean(beanName, mbd);
            }
        }

        // Need to determine the constructor...
        Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
        if (ctors != null ||
                mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
                mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
            return autowireConstructor(beanName, mbd, ctors, args);
        }

        // No special handling: simply use no-arg constructor.
        return instantiateBean(beanName, mbd);
    }

這塊代碼主要是再次對(duì)bean做安全檢查并確定該bean有默認(rèn)的構(gòu)造函數(shù),createBeanInstance()這個(gè)方法最后一行

protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
    try {
        Object beanInstance;
        final BeanFactory parent = this;
        if (System.getSecurityManager() != null) {
            beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
                    getInstantiationStrategy().instantiate(mbd, beanName, parent),
                    getAccessControlContext());
        }
        else {
            beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
        }
        BeanWrapper bw = new BeanWrapperImpl(beanInstance);
        initBeanWrapper(bw);
        return bw;
    }
    catch (Throwable ex) {
        throw new BeanCreationException(
                mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
    }
}

然后我們?cè)倩氐絛oCreateBean()這個(gè)方法,在AbstractAutowireCapableBeanFactory

// Initialize the bean instance.
Object exposedObject = bean;
try {
    //對(duì)bean進(jìn)行填充,將各個(gè)屬性值注入,其中,可能存在依賴與其他bean的屬性,則會(huì)遞歸初始依賴bean
    populateBean(beanName, mbd, instanceWrapper);// sunliang marked
    if (exposedObject != null) {
        //調(diào)用初始化方法,比如init-method
        exposedObject = initializeBean(beanName, exposedObject, mbd);
    }
}

初始化bean,的確,現(xiàn)在bean已經(jīng)實(shí)例化了,開始初始化該bean,進(jìn)入initializeBean(...)這個(gè)方法

if (System.getSecurityManager() != null) {
    AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
        invokeAwareMethods(beanName, bean);
        return null;
    }, getAccessControlContext());
}
else {
    invokeAwareMethods(beanName, bean);
}

接下來進(jìn)入到invokeAwareMethods()方法

private void invokeAwareMethods(final String beanName, final Object bean) {
    if (bean instanceof Aware) {
        if (bean instanceof BeanNameAware) {
            ((BeanNameAware) bean).setBeanName(beanName);
        }
        if (bean instanceof BeanClassLoaderAware) {
            ClassLoader bcl = getBeanClassLoader();
            if (bcl != null) {
                ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
            }
        }
        if (bean instanceof BeanFactoryAware) {
            ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
        }
    }
}

再回到initializeBean()方法中

try {
    invokeInitMethods(beanName, wrappedBean, mbd);
}

protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
        throws Throwable {

    boolean isInitializingBean = (bean instanceof InitializingBean);
    if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
        if (logger.isDebugEnabled()) {
            logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
        }
        if (System.getSecurityManager() != null) {
            try {
                AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
                    ((InitializingBean) bean).afterPropertiesSet();
                    return null;
                }, getAccessControlContext());
            }
            catch (PrivilegedActionException pae) {
                throw pae.getException();
            }
        }
        else {
        //第一部分
            ((InitializingBean) bean).afterPropertiesSet();
        }
    }

    if (mbd != null) {
        String initMethodName = mbd.getInitMethodName();
        if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
                !mbd.isExternallyManagedInitMethod(initMethodName)) {
                //第二部分
            invokeCustomInitMethod(beanName, bean, mbd);
        }
    }
}

首先先判斷該bean是否實(shí)現(xiàn)了InitializingBean,如果實(shí)現(xiàn)了先執(zhí)行afterPropertiesSet這個(gè)方法,然后如果該bean又執(zhí)行了init-method,到此我們的bean創(chuàng)建和加載算是基本完成,下一節(jié)分析一些具體詳細(xì)點(diǎn)的實(shí)現(xiàn)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,106評(píng)論 6 542
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,441評(píng)論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,211評(píng)論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,736評(píng)論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,475評(píng)論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,834評(píng)論 1 328
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,829評(píng)論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,009評(píng)論 0 290
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,559評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,306評(píng)論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,516評(píng)論 1 374
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,038評(píng)論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,728評(píng)論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,132評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,443評(píng)論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,249評(píng)論 3 399
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,484評(píng)論 2 379

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