常見的定義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
這個類來處理的,關鍵**:
privatevoid
loadbeandefinitionsforconfigurationclass(configurationclass configclass,
trackedconditionevaluator trackedconditionevaluator)
//這裡就是處理方法上的@bean
for(beanmethod beanmethod : configclass.getbeanmethods())
//處理@importresource,裡面解析xml就是上面說到的解析xml的xmlbeandefinitionreader
loadbeandefinitionsfromimportedresources(configclass.getimportedresources());
loadbeandefinitionsfromregistrars(configclass.getimportbeandefinitionregistrars());
}
@override通過getbean例項化beanfactory,**是在abstractautowirecapablebeanfactory中public
void preinstantiatesingletons() throws
bean***ception
}, getaccesscontrolcontext());
}else
if(iseagerinit)
}else}}
}
protected object initializebean(final string beanname, finalobject 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進來,...