[源碼]springboot源碼中一窺BeanFactory接口getBean的實現(xiàn)細(xì)節(jié)

先聊聊IOC

IoC(Inversion of Control) 控制反轉(zhuǎn),是spring框架的精髓,簡單來說,就是創(chuàng)建過程你不管,交給容器。與之對應(yīng)的兩個重要的類:

  • BeanFactory - 接口的定義,定義了最基礎(chǔ)的操作接口,具體功能依賴實現(xiàn)類
  • ApplicationContext - 實現(xiàn)了BeanFactory,并擴(kuò)展其功能

spring中的IOC

Spring以往通過xml文件加載bean,過程大致如下:

  • 通過 xml 文件加載,xml文件舉例:
<bean id="hello" class="cn.test.service.Hello">
    <property name="content" value="hello"/>
</bean>
  • 加載相關(guān)屬性
  • 反射實例化對象
  • xml中的autowire
    注意:xml中也可以配置 autowire 會自動注入,參數(shù) byName,意思是通過name去尋找依賴,通過這個方式解決依賴的注入。
<!-- 通過設(shè)置 autowire 屬性,我們就不需要像上面那樣顯式配置依賴了 -->
<bean name="serviceAutowire" class="cn.test.autowire.Service" autowire="byName"/>
  • 解決配置bean太多的問題 引入FactoryBean(注意不是BeanFactory)
  • ApplicationContextAware引入
    在我們的web程序中,用spring來管理各個實例(bean), 有時在程序中為了使用已被實例化的bean, 通常會用到這樣的代碼
ApplicationContext appContext = new ClassPathXmlApplicationContext("applicationContext-common.xml");  
AbcService abcService = (AbcService)appContext.getBean("abcService"); 

這會重新裝載applicationContext-common.xml并實例化上下文bean,如果有些線程配置類也是在這個配置文件中,那么會造成做相同工作的的線程會被啟兩次。一次是web容器初始化時啟動,另一次是上述代碼顯示的實例化了一次。當(dāng)于重新初始化一遍,這樣就產(chǎn)生了冗余。
解決方法
不用類似new ClassPathXmlApplicationContext()的方式,從已有的spring上下文取得已實例化的bean。通過ApplicationContextAware接口進(jìn)行實現(xiàn)。

  • BeanPostProcessor 是 bean 實例化時的后置處理器,包含兩個方法,其源碼如下:
public interface BeanPostProcessor {
    // bean 初始化前的回調(diào)方法
    Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;

    // bean 初始化后的回調(diào)方法    
    Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}

BeanPostProcessor 是 Spring 框架的一個擴(kuò)展點,通過實現(xiàn) BeanPostProcessor 接口,我們就可插手 bean 實例化的過程。比如大家熟悉的 AOP 就是在 bean 實例后期間將切面邏輯織入 bean 實例中的,AOP 也正是通過 BeanPostProcessor 和 IOC 容器建立起了聯(lián)系。

簡單來說:Spring容器從xml配置、java注解、spring注解中讀取bean配置信息,形成bean定義注冊表,填充bean的相關(guān)屬性,應(yīng)用通過getBean方法可以獲取其中的bean并實例化使用。
在Spring中,ClassPathXmlApplicationContext 的構(gòu)造過程,實際就是 Spring IoC 的初始化過程,ClassPathXmlApplicationContext的繼承關(guān)系如下圖:


image.png

BeanFactory的getBean的實現(xiàn)細(xì)節(jié)

回到這個類最基礎(chǔ)的一個方法,我們看getBean的過程是如何實現(xiàn)的。

獲取bean

BeanFactory中只定義了接口,getBean(String)方法實現(xiàn)細(xì)節(jié)體現(xiàn)5個實現(xiàn)類中。


image.png
  • SimpleJndiBeanFactory - spring beanFactory接口的基于jndi的簡單實現(xiàn)
  • StaticListableBeanFactory - 簡化版的BeanFactory,由于未實現(xiàn)BeanDefinitionRegistry,所以并不支持BeanDefinition的注冊操作
  • StubWebApplicationContext - WebApplicationContext的實現(xiàn)
  • AbstractApplicationContext - ApplicationContext是應(yīng)用的配置中的核心接口,應(yīng)用運行過程中是只讀的,但是可以通過實現(xiàn)其中的接口來達(dá)到reload的目的,AbstractApplicationContext是ApplicationContext的抽象類。相比于簡單的BeanFactory,ApplicationContext能在類內(nèi)部檢查特定的bean的定義,這個類會自動注冊BeanFactoryPostProcessor和BeanPostProcessors和ApplicationListeners
  • AbstractBeanFactory - BeanFactory實現(xiàn)的一個抽象基類,我們重點研究。
GetBean過程:AbstractBeanFactory中doGetBean

繼承關(guān)系如下


image.png

BeanFactory實現(xiàn)的一個抽象基類,同時實現(xiàn)了ConfigurableBeanFactory的SPI。這個方法的getBean的實現(xiàn)(實際邏輯在doGetBean中),如下。

    /**
     * 返回一個實例,實例可以是共享的,獨立的或者是一個特定的bean
     * @param name: bean的名稱
     * @param requiredType: bean的類型
     * @param args :其他參數(shù)集合,***僅僅用于創(chuàng)建新對象的時候,而不是獲取一個已經(jīng)存在的對象*** @Nullable 表示可以為空,不能為空用@NotNull修飾
     * @param typeCheckOnly:是否對象只是用來做類型檢查而不是實際要用
     * @return bean的實例
     * @throws BeansException 如果bean不能被創(chuàng)建拋出異常
     */
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
            @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
                
        // 去掉間接引用,去別名,使得最后的beanName是一個最簡的名稱,舉例:
        // 1 有的name名字用&開頭,表示取FactoryBean本身,需要調(diào)用該方法。
        // 2 name是別名,也需要轉(zhuǎn)為對應(yīng)的beanName
        // 其中調(diào)用了BeanFactoryUtils中的方法,這個是bean操作的工具類,也很值得一讀,加個todo
        final String beanName = transformedBeanName(name);
        Object bean;

        // 檢查單例緩存,獲取人工注冊的單例從beanName-->getSingleton獲得object-->getObjectForBeanInstance獲取bean
        // sharedInstance 是從一個 Map<String, Object> singletonObjects結(jié)構(gòu)中獲取的對象,這個對象cache了bean name和bean instance的映射
        // 實際接口調(diào)用過程中,有一些獲取不到,向前置earlySingletonObjects獲取的處理細(xì)節(jié),這里可以看源碼
        Object sharedInstance = getSingleton(beanName);

        // 如果 sharedInstance = null,則說明緩存里沒有對應(yīng)的實例,表明這個實例還沒創(chuàng)建。
       // BeanFactory 并不會在一開始就將所有的單例 bean 實例化好,而是在調(diào)用 getBean 獲取bean的時候?qū)嵗簿褪?lazy加載
        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 + "'");
                }
            }
            // 條件1:如果 sharedInstance 是普通的單例 bean,下面的方法會直接返回。
            // 條件2:如果是FactoryBean,且&開頭,是FactoryBean的解引用,返回FactoryBean,這個也是特殊的bean
            // 條件1,2不滿足,如果sharedInstance是FactoryBean,調(diào)用getObjectFromFactoryBean這個函數(shù)從中獲取Object
            // getObjectFromFactoryBean方法中調(diào)用doGetObjectFromFactoryBean,其中又調(diào)用factory.getObject()方法,這個方法是一個抽象接口,所有的Factory的實現(xiàn)類實現(xiàn)這個接口去create instance
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }

        else {
            // 進(jìn)入這個分支,則表明 sharedInstance 可能為空,
            // 此時 beanName 對應(yīng)的 bean未創(chuàng)建,或者在父類中創(chuàng)建
            // 如果當(dāng)前的bean已經(jīng)創(chuàng)建過(非父類),會返回失敗,應(yīng)該是循環(huán)引用導(dǎo)致的。
            // debug到代碼內(nèi)部,prototypesCurrentlyInCreation.set有個分支:else if (curVal instanceof String)不明白為什么要有這個分支,但是不影響后續(xù)閱讀,這里加個todo。
            if (isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }

            // 檢查bean的定義是否已經(jīng)出現(xiàn)在工廠中
            // 先檢查父親工廠中是否有
            BeanFactory parentBeanFactory = getParentBeanFactory();
            if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
                // 沒找到,就遞歸地向上尋找
                // 遞歸過程中根據(jù)不同的參數(shù)分治
                // getBean 方法有很多重載,工廠模式了解一下
                // 比如 getBean(String name, Object... args),我們在首次獲取,某個 bean 時,可以傳入用于初始化 bean 的參數(shù)數(shù)組(args)
                // BeanFactory 會根據(jù)這些參數(shù),去匹配合適的構(gòu)造方法構(gòu)造 bean 實例。
                String nameToLookup = originalBeanName(name);
                if (parentBeanFactory instanceof AbstractBeanFactory) {
                    return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                            nameToLookup, requiredType, args, typeCheckOnly);
                }
                else if (args != null) {
                    // Delegation to parent with explicit args.
                    return (T) parentBeanFactory.getBean(nameToLookup, args);
                }
                else if (requiredType != null) {
                    // No args -> delegate to standard getBean method.
                    return parentBeanFactory.getBean(nameToLookup, requiredType);
                }
                else {
                    return (T) parentBeanFactory.getBean(nameToLookup);
                }
            }

            // 用alreadyCreated保存需要創(chuàng)建的beanName,如果只是做typeCheck,可以不用創(chuàng)建bean
            if (!typeCheckOnly) {
                markBeanAsCreated(beanName);
            }
                      
                        
            try {
                // 貫穿父子關(guān)系去獲取RootBeanDefinition
                // RootBeanDefinition是BeanDefinition最常用地實現(xiàn)類,對應(yīng)配置文件中bean元素標(biāo)簽。在配置文件中可以定義父<bean>和子<bean>,父<bean>用RootBeanDefiniton表示,子<bean>用ChildBeanDefinition表示。
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                // 當(dāng)前版本spring-beans-5.1.10只是在檢查 !mbd.isAbstract()
                checkMergedBeanDefinition(mbd, beanName, args);

                // 初始化bean的依賴,舉例:初始化一個店鋪,店鋪內(nèi)有基本的設(shè)施,店鋪依賴設(shè)施,這里先檢查設(shè)施能否初始化。
                // todo:這里有個好奇,setDependsOn什么時候被賦值的?
                String[] dependsOn = mbd.getDependsOn();
                if (dependsOn != null) {
                    for (String dep : dependsOn) {
                        // 再次檢查是否包含循環(huán)依賴
                        // 這里是最樸素的循環(huán)依賴檢查邏輯,內(nèi)部是深度優(yōu)先遍歷,
                        // 找到A的依賴B的集合set<B>,然后判斷set<B>的每個元素的依賴集合中是否依賴A
                        if (isDependent(beanName, dep)) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                        }
                        // 給當(dāng)前bean注冊一個依賴bean,對應(yīng)下面的dep,銷毀順序是:依賴bean銷毀后,當(dāng)前bean才被銷毀
                        // 注冊后,下次判斷循環(huán)依賴有可以檢查到這次新注冊的這組依賴關(guān)系 
                        registerDependentBean(dep, beanName);
                        try {
                            // 遞歸調(diào)用自己,來做檢查,好多冗余操作啊...
                            getBean(dep);
                        }
                        catch (NoSuchBeanDefinitionException ex) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                        }
                    }
                }

                // 創(chuàng)建bean的實例,其中核心方法是createBean和getObjectForBeanInstance,這一大段只不過是區(qū)分單例,原型和其他的處理情況而已。
                // todo: 有時間要再讀讀createBean和getObjectForBeanInstance的源碼。
                // 單例情況
                if (mbd.isSingleton()) {
                    // 從匿名函數(shù)返回中獲取單例對象
                    sharedInstance = getSingleton(beanName, () -> {
                        try {
                            // 創(chuàng)建一個bean
                            // todo:create是一個抽象接口,具體的實現(xiàn)邏輯在子類中,這里以后有時間可以讀一下源碼
                            return createBean(beanName, mbd, args);
                        }
                        catch (BeansException ex) {
                            // 從緩存中明確的移除單例:避免在創(chuàng)建流程中因為緩存導(dǎo)致的循環(huán)引用,同時移除任何關(guān)于這個bean的臨時引用。
                            // 刪除的位置包含singletonObjects,singletonFactories,earlySingletonObjects,registeredSingletons,disposableBeans,dependentBeanMap
                            destroySingleton(beanName);
                            throw ex;
                        }
                    });
                    // 從bean的實例中獲取對象
                    // bean的實例可能是一個普通bean,也可能是FactoryBean,如果是普通Bean可以直接返回,如果是FactoryBean,需要從中再獲取到bean的實例。這個方法前面也提到過
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }

                // 如果是原型(參考原型模式的概念)
                else if (mbd.isPrototype()) {
                    // 如果是原型,創(chuàng)建一個新實例
                    Object prototypeInstance = null;
                    try {
                        beforePrototypeCreation(beanName);
                        prototypeInstance = createBean(beanName, mbd, args);
                    }
                    finally {
                        afterPrototypeCreation(beanName);
                    }
                    bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                }

                else {
                    // 非單例,非原型的方式獲取bean
                    // 獲取作用域
                    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) {
                cleanupAfterBeanCreationFailure(beanName);
                throw ex;
            }
        }

        // 類型檢查:判斷需要的類型是否匹配實際的bean實例。
        if (requiredType != null && !requiredType.isInstance(bean)) {
            try {
                // todo: 通過類型轉(zhuǎn)化來判斷是否類型匹配,這個方法的源碼也值得一讀。
                T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
                if (convertedBean == null) {
                    throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
                }
                return convertedBean;
            }
            catch (TypeMismatchException ex) {
                if (logger.isTraceEnabled()) {
                                        // todo: ClassUtils也是一個值得讀源碼的工具類
                    logger.trace("Failed to convert bean '" + name + "' to required type '" +
                            ClassUtils.getQualifiedName(requiredType) + "'", ex);
                }
                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
            }
        }
        return (T) bean;
    }

主要流程已經(jīng)在代碼的注釋中寫清楚了,重點的幾個邏輯我再總結(jié)一下:
1 去掉間接引用,去別名,使得最后的beanName是一個最簡的名稱transformedBeanName(name)
2 檢查單例緩存,獲取人工注冊的單例中獲取對象,利用該對象生成bean,生成方法中區(qū)分對待一般的bean和FactoryBean
3 第2步驟如果為null,從父類中獲取bean和FactoryBean
4 父類中沒有的話合并 BeanDefinition
5 處理 depends-on 依賴
6 創(chuàng)建并緩存 bean
7 調(diào)用 getObjectForBeanInstance 方法,生成 bean 實例
8 類型檢查和轉(zhuǎn)化

CreateBean過程

看上述核心代碼,我們不難發(fā)現(xiàn),有一個核心函數(shù)getSingleton一直在被調(diào)用

image.png

這個方法中傳入了一個匿名函數(shù),匿名函數(shù)中調(diào)用createBean,這是我們創(chuàng)建bean 的一段核心邏輯。我們先來看下getSingleton的代碼邏輯


public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
        Assert.notNull(beanName, "Bean name must not be null");
        synchronized (this.singletonObjects) {
            // 緩存中獲取bean,不為空則直接返回
            Object singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null) {
                if (this.singletonsCurrentlyInDestruction) {
                    throw new BeanCreationNotAllowedException(beanName,
                            "Singleton bean creation not allowed while singletons of this factory are in destruction " +
                            "(Do not request a bean from a BeanFactory in a destroy method implementation!)");
                }
                if (logger.isDebugEnabled()) {
                    logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
                }

                // beforeSingletonCreation 將bean添加到 singletonsCurrentlyInCreation 的集合中,集合中存放的是正在創(chuàng)建的bean
                beforeSingletonCreation(beanName);
                boolean newSingleton = false;
                boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
                if (recordSuppressedExceptions) {
                    this.suppressedExceptions = new LinkedHashSet<>();
                }
                try {
                    singletonObject = singletonFactory.getObject();
                    newSingleton = true;
                }
                catch (IllegalStateException ex) {
                    // Has the singleton object implicitly appeared in the meantime ->
                    // if yes, proceed with it since the exception indicates that state.
                    singletonObject = this.singletonObjects.get(beanName);
                    if (singletonObject == null) {
                        throw ex;
                    }
                }
                catch (BeanCreationException ex) {
                    if (recordSuppressedExceptions) {
                        for (Exception suppressedException : this.suppressedExceptions) {
                            ex.addRelatedCause(suppressedException);
                        }
                    }
                    throw ex;
                }
                finally {
                    if (recordSuppressedExceptions) {
                        this.suppressedExceptions = null;
                    }
                    // 創(chuàng)建完成,將bean從正在創(chuàng)建的集合中移除
                    afterSingletonCreation(beanName);
                }
                if (newSingleton) {
                    // 將 <beanName, singletonObject> 映射緩存到 singletonObjects中
                    addSingleton(beanName, singletonObject);
                }
            }
            return singletonObject;
        }
    }

總結(jié)一下上述過程:

  • 1 從singletonObjects獲取能獲取則直接獲取,singletonObjects可以看作緩存
  • 2 不能獲取進(jìn)入創(chuàng)建流程,先將 beanName 添加到 singletonsCurrentlyInCreation
  • 3 getObject 調(diào)用 createBean 方法,創(chuàng)建bean
  • 4 beanName 從 singletonsCurrentlyInCreation 中移除
  • 5 <beanName, singletonObject> 添加至 singletonObjects

createBean是流程中創(chuàng)建bean的核心方法,我們繼續(xù)看下這個createBean方法的實現(xiàn)??梢运岩幌乱韵潞瘮?shù)

return createBean(beanName, mbd, args);

在AbstractBeanFactory中只定義了一個抽象接口

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

接口的實現(xiàn)在AbstractAutowireCapableBeanFactory中的createBean方法
createBean方法和getBean方法有一些類似,就是真正getBean前后都做了很多事情,getBean的核心邏輯封裝在另外一個方法中。
這里就不帖詳細(xì)的源碼了,整個代碼結(jié)構(gòu)就是如下形式:

  • pre-createBean:
    • 解析bean的類型
    • prepareMethodOverrides,override method的處理,實際在處理lookup-method 和 replace-method 配置(bean配置中的兩個關(guān)鍵字)
    • 初始化前應(yīng)用后置處理 resolveBeforeInstantiation,后置處理返回的 bean 不為空,則直接返回(這里也可能返回bean)
  • 核心邏輯:Object beanInstance = doCreateBean(beanName, mbdToUse, args);
  • post-createBean:日志記錄,返回對象

resolveBeforeInstantiation會生成bean,但是我們這里先不聊,因為和AOP原理相關(guān),這里先不擴(kuò)展,另外一個生成bean的核心邏輯寫在doCreateBean中。我們具體看這個方法的實現(xiàn)。
ps:spring框架中,真實的執(zhí)行邏輯一般都放在do開頭的方法中,doCreateBean也是一樣。

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

        // bean初始化
        // BeanWrapper 是bean 的包裝類,通過這個包裝,能方便的設(shè)置和獲取bean的實例屬性
        BeanWrapper instanceWrapper = null;

        // 單例先從factoryBeanInstanceCache移除,返回為null表示不存在,那么直接用createBeanInstance創(chuàng)建
        if (mbd.isSingleton()) {
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        if (instanceWrapper == null) {
            // createBeanInstance創(chuàng)建createBean,使用三種策略之一:
            // factory method, constructor autowiring 或者 simple instantiation
            // factory method, 工廠方法
            // constructor autowiring,構(gòu)造方式自動注入
            // simple instantiation,通過無參數(shù)構(gòu)造方法
            // 另外bean的信息配置了lookup-method和replace-method會另外處理。
            // 返回類型是BeanWrapper,能用于填充對象的屬性,todo:BeanWrapper的源碼也值得讀一讀。
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        // 原始的bean,還沒有填充屬性
        final Object bean = instanceWrapper.getWrappedInstance();
        Class<?> beanType = instanceWrapper.getWrappedClass();
        if (beanType != NullBean.class) {
            mbd.resolvedTargetType = beanType;
        }

        // 允許后置處理器post-processors 修改 MBD
        synchronized (mbd.postProcessingLock) {
            // postProcessed默認(rèn)為false
            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;
            }
        }

        // 緩存單例用于解決循環(huán)依賴,earlySingletonExposure用于表示是否提前暴露,即使生命周期處理接口帶來的循環(huán)依賴也包含
        // earlySingletonExposure的滿足的條件:
        // 條件: bean 是否是單例類型 & 允許循環(huán)依賴 &  bean 是處于創(chuàng)建的狀態(tài)中
        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");
            }
            // 匿名函數(shù)獲取早期bean引用,如果bean中的方法被AOP切點匹配到,會進(jìn)入aop相關(guān)邏輯
            addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
        }

        // 初始化bean的實例
        Object exposedObject = bean;
        try {
            // 給bean裝載屬性,也是一個核心方法,todo:值得一讀的源碼
            populateBean(beanName, mbd, instanceWrapper);
            // 剩余的初始化工作
            exposedObject = initializeBean(beanName, exposedObject, mbd);
        }
        catch (Throwable ex) {
            if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
                throw (BeanCreationException) ex;
            }
            else {
                throw new BeanCreationException(
                        mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
            }
        }

        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()) {
                        throw new BeanCurrentlyInCreationException(beanName,
                                "Bean with name '" + beanName + "' has been injected into other beans [" +
                                StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
                                "] in its raw version as part of a circular reference, but has eventually been " +
                                "wrapped. This means that said other beans do not use the final version of the " +
                                "bean. This is often the result of over-eager type matching - consider using " +
                                "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
                    }
                }
            }
        }

        // 注冊bean,為當(dāng)前bean的銷毀提供策略和實現(xiàn)
        try {
            registerDisposableBeanIfNecessary(beanName, bean, mbd);
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
        }

        return exposedObject;
    }

以上創(chuàng)建過程給各小結(jié):

  • 緩存中獲取BeanWrapper,獲取不到就創(chuàng)建BeanWrapper
  • 一些預(yù)處理,MergedBeanDefinitionPostProcessor; 暴露 bean 的早期引用(early reference),用于處理循環(huán)依賴問題
  • populateBean填充屬性
  • initializeBean進(jìn)行剩下的初始化
  • 注冊銷毀邏輯

createBeanInstance

doCreateBean這個方法中,有個很重要的核心方法createBeanInstance。
復(fù)述一下前面的批注:
createBeanInstance創(chuàng)建createBean,使用三種策略之一:

  • factory method, constructor autowiring 或者 simple instantiation
  • factory method, 工廠方法
  • constructor autowiring,構(gòu)造方式自動注入
  • simple instantiation,通過無參數(shù)構(gòu)造方法,另外bean的信息配置了lookup-method和replace-method會另外處理。返回類型是BeanWrapper,能用于填充對象的屬性
instanceWrapper = createBeanInstance(beanName, mbd, args);

下面重點剖析這段代碼

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);
        // 檢測訪問權(quán)限,默認(rèn)情況下,對于public的類有訪問權(quán)限,沒有訪問權(quán)限拋出異常
        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);
        }

        // 工廠方法不為空,通過工廠方法構(gòu)建bean對象
        if (mbd.getFactoryMethodName() != null) {
            return instantiateUsingFactoryMethod(beanName, mbd, args);
        }

        // Shortcut when re-creating the same bean...
        // 如果是處理同一個bean,第一次處理的時候,做個標(biāo)記,之后同類型的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 {
                // 默認(rèn)方法構(gòu)造bean對象
                return instantiateBean(beanName, mbd);
            }
        }

        // 通過后處理器返回一系列構(gòu)造方法
        Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
        // 條件mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR:bean的autowire屬性是否為constructor
        // 條件mbd.hasConstructorArgumentValues(): bean中是否配置了<construct-arg/>
        if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
                mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
            return autowireConstructor(beanName, mbd, ctors, args);
        }

        // Preferred constructors for default construction?
        ctors = mbd.getPreferredConstructors();
        if (ctors != null) {
            return autowireConstructor(beanName, mbd, ctors, null);
        }

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

autowireConstructor

上面的代碼通過不同的條件選擇調(diào)用autowireConstructor,
這個方法比較復(fù)雜,到了這一步已經(jīng)大致知道創(chuàng)建過程是如何的了,
這一層后續(xù)繼續(xù)詳解吧。
springboot中BeanWrapper的生成方法autowireConstructor

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容