欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot?Bean實(shí)例化流程解析

 更新時(shí)間:2023年08月28日 09:58:24   作者:LBruse  
在SpringBoot啟動(dòng)過程中會(huì)執(zhí)行refreshContext()方法,而在其執(zhí)行過程中,又會(huì)調(diào)用finishBeanFactoryInitialization()方法,該方法負(fù)責(zé)了Bean的實(shí)例化,那么本文將從源碼跟讀的角度來解析一下具體流程

前置工作

新建一個(gè)RestService,代碼如下

package geek.springboot.application.service;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
/**
 * Rest Service
 *
 * @author Bruse
 */
@Slf4j
@Service
public class RestService {
    @PostConstruct
    public void init() {
        log.info("RestService init....");
    }
}

finishBeanFactoryInitialization

來到 AbstractApplicationContext refresh() 方法,在該方法中調(diào)用了 finishBeanFactoryInitialization() 方法

image.png

判斷是否存在conversionService

首先判斷當(dāng)前IOC容器中是否存在 conversionService ,有的話將其設(shè)置到 BeanFactory

image.png

判斷是否已有BeanFactoryPostProcessor

接下來判斷當(dāng)前 BeanFactory 中是否存在 BeanFactoryPostProcessor ,沒有的話注冊一個(gè)默認(rèn)的實(shí)現(xiàn)

image.png

初始化LoadTimeWeaverAware

接著查詢當(dāng)前IOC容器中是否存在 LoadTimeWeaverAware 的實(shí)現(xiàn),有的話則進(jìn)行初始化。該類是使用AOP時(shí)做織入的一個(gè)工具類,一般情況下開發(fā)不會(huì)使用到它,所以這里其實(shí)并不會(huì)執(zhí)行到循環(huán)體中的 getBean()

image.png

停止使用TempClassLoader

接下來將 BeanFactory tempClassLoader 屬性設(shè)置為null

image.png

調(diào)用freezeConfiguration()

接下來調(diào)用 freezeConfiguration() 方法,該方法主要是做一個(gè) 凍結(jié) 聲明,即聲明在此期間無法再向 BeanFactory 注冊新的Bean定義

image.png

image.png

調(diào)用preInstantiateSingletons()

最后也是最關(guān)鍵的,調(diào)用 preInstantiateSingletons() 方法進(jìn)行Bean的實(shí)例化

image.png

實(shí)例化Bean

最終其實(shí)會(huì)調(diào)用到 DefaultListableBeanFactor preInstantiateSingletons() 方法。

首先會(huì)獲取當(dāng)前所有Bean定義的名稱,并進(jìn)行遍歷

image.png

Tips:除了之前定義的service,controller,config...也包含了Spring內(nèi)置的一些Bean

接著根據(jù)名稱獲取相關(guān)的 BeanDefinition ,也就是Bean的定義,它包括了Bean的一些元信息,比如是否單例,是否延遲初始化,該Bean依賴項(xiàng)等。

image.png

Tips:這里為了避免混淆視聽,我事先已經(jīng)在debug斷點(diǎn)處加上了觸發(fā)條件,只有beanName是restService時(shí),斷點(diǎn)才生效。

image.png

可以看到Spring會(huì)先根據(jù) BeanDefinition 判斷出當(dāng)前類是否 抽象類 ,是否 單例 ,是否 延遲加載 。只有當(dāng)當(dāng)前 BeanDefinition 滿足既不是 抽象類 ,也不 延遲加載 單例 時(shí),才會(huì)進(jìn)行操作。

接著還會(huì)判斷當(dāng)前 Bean 是否實(shí)現(xiàn)了 FactoryBean 的接口,是的話則還要對 Bean 做一些處理。

因?yàn)橹皠?chuàng)建的 RestService 沒有實(shí)現(xiàn) FactoryBean 接口,所以直接調(diào)用 getBean 方法

image.png

doGetBean

接著走到 AbstractBeanFactory doGetBean() 方法,該方法主要作用就是返回一個(gè)指定的Bean實(shí)例

image.png

transformedBeanName

首先是對 Bean 的名稱做一個(gè)處理,其中包含了若 BeanName 中包含了 FACTORY_BEAN_PREFIX 的話,則將其從 BeanName 中刪除的邏輯

image.png

同時(shí)如果有設(shè)置 別名 的話,也會(huì)獲取真正的 BeanName 再返回

image.png

getSingleton

接著進(jìn)入 DefaultSingletonBeanRegistry getSingleton 方法,該方法主要作用是 返回給定名稱注冊的單例對象

image.png

雖然這里邏輯很長,還用到了 雙檢鎖 機(jī)制,但是其實(shí)從 singletonObjects 中檢查是否有對應(yīng) beanName Bean 存在時(shí),因?yàn)槭堑谝淮蝿?chuàng)建,所以 singletonObjects 中并不存在相關(guān)的 Bean ,直接沒進(jìn) if 方法體,就返回 null

image.png

isPrototypeCurrentlyInCreation

image.png

接著執(zhí)行 AbstractBeanFactory isPrototypeCurrentlyInCreation 方法,該方法主要是檢查該 beanName 相關(guān)的 Bean 是否在當(dāng)前線程創(chuàng)建中,因?yàn)槲覀冞@里還沒有進(jìn)行創(chuàng)建,所以這里方法返回false。

獲取BeanFactory

image.png

接著嘗試獲取父類 BeanFactory ,并調(diào)用父類 BeanFactory getBean 方法獲取 Bean ,但是因?yàn)楫?dāng)前的 beanFactory 已經(jīng)是最頂級(jí)的了,所以直接跳過大段代碼。

Tips:Spring中BeanFactory跟JVM實(shí)現(xiàn)雙親委派機(jī)制的ClassLoader一樣,也存在子級(jí)父級(jí)關(guān)系

markBeanAsCreated

接著執(zhí)行 markBeanAsCreated 方法,這里也用到了 雙檢鎖 機(jī)制,方法很簡單,就是將 beanName 添加到 alreadyCreated 當(dāng)中,算是做一個(gè)標(biāo)識(shí),標(biāo)識(shí)當(dāng)前 beanName 對應(yīng)的 Bean 正在創(chuàng)建當(dāng)中。

image.png

getMergedLocalBeanDefinition

接著調(diào)用 getMergedLocalBeanDefinition 方法獲取 BeanDefinition ,并檢查是否是抽象類,是的話直接拋出異常

image.png

image.png

檢查是否存在依賴

image.png

接著檢查當(dāng)前要實(shí)例化的 Bean 是否和別的Bean存在依賴關(guān)系,是的話得先把所依賴的 Bean 創(chuàng)建好,才能繼續(xù)實(shí)例化當(dāng)前的 Bean 。

因?yàn)?RestService 中沒有依賴什么別的 Bean ,所以這里略過一段代碼

根據(jù)作用域創(chuàng)建Bean

接著便是根據(jù)作用域的不同,使用不同方式創(chuàng)建 Bean

image.png

getSingleton

這里進(jìn)入 DefaultSingletonBeanRegistry getSingleton 方法

image.png

這里首先還是會(huì)檢查當(dāng)前 Bean 是否已初始化,是的話直接返回

image.png

createBean

接著調(diào)用 ObjectFactory getObject 方法,因?yàn)閭鲄r(shí)是傳遞了一個(gè) 匿名內(nèi)部類 ,所以重新回到 AbstractBeanFactory ,可以看到調(diào)用了 createBean 方法

image.png

resolveBeanClass

接著來到 AbstractAutowireCapableBeanFactory createBean 方法,首先會(huì)調(diào)用 AbstractBeanFactory resolveBeanClass 方法對 BeanDefinition 對應(yīng)的 Class 做一個(gè)解析,這里因?yàn)橹耙呀?jīng)過了,所以直接返回。

image.png

image.png

resolveBeforeInstantiation

image.png

接著來到 resolveBeforeInstantiation 方法,可以看到如果它返回的 Bean 不為空,那么將直接返回,意味著 Bean 實(shí)例化完成。

接著深入查看具體實(shí)現(xiàn)細(xì)節(jié),可以看到會(huì)判斷當(dāng)前IOC容器是否存在 InstantiationAwareBeanPostProcessor 接口的實(shí)現(xiàn)

image.png

如果存在 InstantiationAwareBeanPostProcessor 接口實(shí)現(xiàn),則會(huì)調(diào)用其 postProcessBeforeInstantiation 方法,如果該方法返回值不為空,那么直接返回,并且調(diào)用 postProcessAfterInitialization 方法再對返回值做一些處理

image.png

image.png

因?yàn)楫?dāng)前項(xiàng)目中并沒有存在 InstantiationAwareBeanPostProcessor 接口實(shí)現(xiàn),所以直接返回的是 null

doCreateBean

所以初始化 Bean 的重任還是交給了 doCreateBean 方法

image.png

首先判斷當(dāng)前 Bean 是否單例,是的話將其從 factoryBeanInstanceCache 中移除

image.png

createBeanInstance

接著進(jìn)入 createBeanInstance 方法,首先調(diào)用 getInstanceSupplier 方法判斷當(dāng)前 BeanDefinition 是否從其它配置加載的,然后調(diào)用 getFactoryMethodName 方法判斷當(dāng)前 BeanDefinition 是否存在工廠方法, RestService 兩個(gè)條件都不滿足,所以會(huì)一路執(zhí)行到后續(xù)代碼。

image.png

determineConstructorsFromBeanPostProcessors

接著執(zhí)行到 determineConstructorsFromBeanPostProcessors 方法,該方法主要是 確定使用哪個(gè)構(gòu)造器來初始化Bean

image.png

可以看到內(nèi)部實(shí)現(xiàn)其實(shí)是依靠調(diào)用 SmartInstantiationAwareBeanPostProcessor determineCandidateConstructors 方法來進(jìn)行確定的

image.png

但其實(shí)最后返回的是 null

image.png

instantiateBean 

最后來到 instantiateBean 方法,由注釋也可以看出,該方法就是在 Bean 無需做特殊處理,調(diào)用默認(rèn)無參構(gòu)造函數(shù)即可初始化時(shí)調(diào)用的。

image.png

image.png

首先調(diào)用 getInstantiationStrategy 方法獲取 實(shí)例化策略 ,可以看到默認(rèn) 實(shí)例化策略 CglibSubclassingInstantiationStrategy

image.png

instantiate

接著調(diào)用 instantiate 方法,在該方法中利用反射機(jī)制獲取 類默認(rèn)構(gòu)造函數(shù)

image.png

BeanUtils.instantiateClass

最后調(diào)用 BeanUtils instantiateClass 方法進(jìn)行構(gòu)建,可以看出其實(shí)該方法內(nèi)部就是用了Java的 反射機(jī)制 進(jìn)行類的實(shí)例構(gòu)建

image.png

BeanWrapper

Bean 實(shí)例成功創(chuàng)建后,會(huì)創(chuàng)建 BeanWrapper 實(shí)例來對 Bean 實(shí)例做一個(gè)包裝,并調(diào)用 initBeanWrapper 方法對 BeanWrapper 進(jìn)行初始化操作

image.png

可以看到最后返回的不是 BeanInstance ,而是把 BeanInstance 給包裹了一層,返回的 BeanWrapper 。

image.png

applyMergedBeanDefinitionPostProcessors

接著調(diào)用 applyMergedBeanDefinitionPostProcessors 方法,該方法本質(zhì)即獲取所有 MergedBeanDefinitionPostProcessor 實(shí)現(xiàn),并逐個(gè)調(diào)用其 postProcessMergedBeanDefinition 方法

image.png

image.png

populateBean

接著執(zhí)行 populateBean 方法,該方法主要用來填充當(dāng)前的 BeanInstance

image.png

會(huì)獲取當(dāng)前 BeanDefinition 的所有 Property ,并判斷以何種方式進(jìn)行自動(dòng)注入,根據(jù)類型?根據(jù)名稱?

image.png

還可以看到會(huì)嘗試獲取所有 InstantiationAwareBeanPostProcessor 實(shí)現(xiàn),并調(diào)用其 postProcessProperties 方法

image.png

總結(jié)

在Spring實(shí)例化Bean的過程中, BeanDefinition 幾乎貫穿了整個(gè)流程,而 BeanDefinition 是一個(gè)對象在Spring中的描述,Spring通過操作 BeanDefinition 來完成 Bean 的實(shí)例化和屬性注入,而實(shí)例化的過程中又使用到了Java中非?;A(chǔ)且重要的—— 反射

以上就是SpringBoot Bean實(shí)例化流程解析的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot Bean實(shí)例化的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評論