Spring多種載入Bean方式簡析

2021-07-31 18:21:36 字數 3347 閱讀 5274

常見的定義bean的方式有:

雖然這三種定義bean的方式不一樣,對應的處理細節也不一樣,但是從大的邏輯上來看,都是一樣。主要的流程如下圖: 最關鍵的就是問題就是這麼去找到定義bean的方式,然後生成beandefinition後註冊到spring上下文中,由spring自動建立bean的例項。

beandefinition是乙個介面,用來描述乙個bean例項,例如是singleton還是prototype,屬性的值是什麼,建構函式的引數是什麼等。簡單來說,通過乙個beandefinition我們就可以完成乙個bean例項化。 beandefinition及其主要的子類:

下面簡單說一下各個子類:

通過xml定義bean是最早的spring定義bean的方式。因此,怎麼把xml標籤解析為beandefinition(), 入口是在org.springframework.beans.factory.xml.xmlbeandefinitionreader這個類,但是實際幹活的是在org.springframework.beans.factory.xml.beandefinitionparserdelegate。**很多,但實際邏輯很簡單,就是解析spring定義的等標籤 。 之前寫過一篇文章介紹過如何自定義spring標籤 ,並解析後註冊到spring中——傳送門

如果要使用@component等註解定義bean,乙個前提條件是:有或者@componentscan註解。但這2個方式還是有一點點區別:

由於是乙個xml標籤,因此是在解析xml,生成的類org.springframework.context.annotation.componentscanbeandefinitionparser,關鍵**:

@override

public

beandefinition parse(element element, parsercontext parsercontext)

註解對應生成的類是org.springframework.context.annotation.componentscanannotationparser其實最後實際幹活的還是classpathbeandefinitionscanner這個。componentscanannotationparser類的生成是伴隨著@configuration這個註解處理過程中(意思說@componentscan必須和@configuration一起使用)。而處理@configuration其實是org.springframework.context.annotation.configurationclasspostprocessor。是不是感覺有點繞。

其實簡單來說,在處理@configuration的時候發現有@componentscan註解,就會生成componentscanannotationparser去掃瞄@component註解

上面說到了,無論註解還是標籤的方式,最後都會交給classpathbeandefinitionscanner這個類來處理,這個類做的就是1.掃瞄basepackage下所有class,如果有@component等註解,讀取@component相關屬性,生成scannedgenericbeandefinition,註冊到spring中。

前面說了@componentscan是在@configuration處理過程中的一環,既然@bean註解也是必須和@configuration一起使用,那麼說明@bean的處理也是在@configuration中,其實最後是交給configurationclassbeandefinitionreader這個類來處理的,關鍵**:

private

void

loadbeandefinitionsforconfigurationclass(configurationclass configclass,

trackedconditionevaluator trackedconditionevaluator)

//這裡就是處理方法上的@bean

for(beanmethod beanmethod : configclass.getbeanmethods())

//處理@importresource,裡面解析xml就是上面說到的解析xml的xmlbeandefinitionreader

loadbeandefinitionsfromimportedresources(configclass.getimportedresources());

loadbeandefinitionsfromregistrars(configclass.getimportbeandefinitionregistrars());

}

@override

public

void preinstantiatesingletons() throws

bean***ception

}, getaccesscontrolcontext());

}else

if(iseagerinit)

}else}}

}

通過getbean例項化beanfactory,**是在abstractautowirecapablebeanfactory中

protected object initializebean(final string beanname, final

object bean, rootbeandefinition mbd)

}, getaccesscontrolcontext());

}else

if (mbd == null || !mbd.issynthetic())

try

catch

(throwable ex)

if (mbd == null || !mbd.issynthetic())

return

}

從上面初始化和注釋內容可以看出,initializebean介面的方法(以及init-method)和beanpostprocessors的呼叫順序
綜上分析,spring載入bean其實大的思想都是一樣的,先讀取相關資訊生成beandefinition,然後通過beandefinition初始化bean。如果知道了上面了套路以後,就可以清楚怎麼自定義xml標籤或者自定義註解向spring中注入bean。

spring動態載入bean

廢話不多說,直接上 private static final string strs new string protected mapremotes new hashmap for int i 0 i string name one if i 0 beandefinitionbuilder user...

Spring控制Bean載入順序

spring容器載入bean順序是不確定的,spring框架沒有約定特定順序邏輯規範。首先要了解depends on或 dependson作用,是用來表示乙個bean a的例項化依賴另乙個bean b的例項化,但是a並不需要持有乙個b的物件,如果需要的話就不用depends on,直接用依賴注入就可...

spring載入bean例項化順序

有乙個bean為 a,乙個bean為b。想要a在容器例項化的時候的乙個屬性name賦值為b的乙個方法funb的返回值。如果只是在a裡單純的寫著 private b b private string name b.funb 會報錯說nullpointexception,因為這個時候b還沒被set進來,...