Bean 工廠使用 Bean 的構(gòu)造函數(shù)創(chuàng)建 Bean 對(duì)象之后,緊接著它會(huì)做一件非常重要的工作——Bean 的初始化。它會(huì)根據(jù)配置信息設(shè)置 Bean 的屬性和依賴對(duì)象,執(zhí)行相應(yīng)的初始化方法。
一般不推薦在大型的應(yīng)用系統(tǒng)中使用自動(dòng)裝配。當(dāng)然,它可以很好的用于小型應(yīng)用系統(tǒng)。如果一個(gè) Bean 聲明被標(biāo)志為“autowire(自動(dòng)裝配)”,bean 工廠會(huì)自動(dòng)將其他的受管對(duì)象與其要求的依賴關(guān)系進(jìn)行匹配,從而完成對(duì)象的裝配——當(dāng)然,只有當(dāng)對(duì)象關(guān)系無歧義時(shí)才能完成自動(dòng)裝配。因?yàn)椴恍枰鞔_指定某個(gè)協(xié)作對(duì)象,所以可以帶來很多的便利性。
舉個(gè)例子,如果在 Bean 工廠中有一個(gè)SessionFactory
類型的實(shí)例,HibernateUserDao 的sessionFactory
屬性就可以獲得這個(gè)實(shí)例。這里可以使用autowire
屬性,就象這樣:
<bean id="userDao" class="com.dev.spring.simple.HibernateUserDao" autowire=”byType”>
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate.LocalSessionFactoryBean">
?????? …..
</bean>
注意,在userDao
的定義中并沒有明確引用sessionFactory
。由于它的“autowire”被設(shè)置為“byType”,所有只要userDao
有一個(gè)類型為SessionFactory
的屬性并有一個(gè) set 方法,Bean 工廠就會(huì)自動(dòng)將sessionFactory
組裝到userDao
中。
如果一個(gè)應(yīng)用有兩個(gè)數(shù)據(jù)庫(kù),這時(shí)就對(duì)應(yīng)有兩個(gè)SessionFactory
。這時(shí) autowire="byType"就無法使用了。我們可以使用另外一種自動(dòng)裝配方式“byName”。它將根據(jù)屬性的名稱來匹配依賴對(duì)象,這樣如果你的配置文件中可以同時(shí)存在多個(gè)類型相同的SessionFactory
,只要他們定義的名稱不同就可以了。這種方式的缺點(diǎn)是:需要精確匹配 Bean 的名稱,即必須要保證屬性的名稱和它所依賴的 Bean 的名稱相等,這樣比較容易出錯(cuò)。
(舉例:Aa 對(duì)象依賴 Bb 對(duì)象。)
注意:我們還是強(qiáng)烈推薦手工指定 Bean 之間的依賴關(guān)系。這種用法最強(qiáng)大,因?yàn)樗试S按名稱引用特定的 Bean 實(shí)例,即使多個(gè) Bean 具有相同類型也不會(huì)混淆。同時(shí),你可以清楚的知道一個(gè) Bean 到底依賴哪些其它的 Bean。如果使用自動(dòng)裝載,你只能去 Bean 的代碼中了解。甚至,Bean 工廠也許會(huì)自動(dòng)裝載一些你根本不想依賴的對(duì)象。
如果你希望 Bean 嚴(yán)格的設(shè)置所有的屬性,“dependency-check”(依賴檢查)屬性將會(huì)非常有用。它默認(rèn)為“none”,不進(jìn)行依賴檢查。“simple”會(huì)核對(duì)所有的原始類型和 String 類型的屬性?!皁bjects”只做對(duì)象間的關(guān)聯(lián)檢查(包括集合)。“all”會(huì)檢查所有的屬性,包括“simple”和“objects”。
舉個(gè)例子:一個(gè) Bean 有如下的一個(gè)屬性:
private int intVar = 0;
public void setIntVar(int intVar) {
??????? this.intVar = intVar;
}
這個(gè) Bean 的配置文件設(shè)置了“dependency-check=”simple””。如果這個(gè)Bean的配置中沒有定義這個(gè)屬性“intVar”,則在進(jìn)行這個(gè) Bean 的依賴檢查時(shí)就會(huì)拋出異常:org.springframework.beans.factory.UnsatisfiedDependencyException。
set
方法非常簡(jiǎn)單,它會(huì)給 class 注入所有依賴的屬性。這些屬性都必須是在配置文件中使用
有兩種方法可以實(shí)現(xiàn) Bean 的之前初始化方法。
InitializingBean
并實(shí)現(xiàn)它的afterPropertiesSet()
方法。接口InitializingBean
的代碼如下:public interface InitializingBean {
void afterPropertiesSet() throws Exception;
}
在 JavaBean 的所有屬性設(shè)置完成以后,容器會(huì)調(diào)用afterPropertiesSet()
方法,應(yīng)用對(duì)象可以在這里執(zhí)行任何定制的初始化操作。這個(gè)方法允許拋出最基本的Exception
異常,這樣可以簡(jiǎn)化編程模型。
在 Spring 框架內(nèi)部,很多 bean 組件都實(shí)現(xiàn)了這些回調(diào)接口。但我們的 Bean 組件最好不要通過這種方式實(shí)現(xiàn)生命周期的回調(diào),因?yàn)樗蕾囉?Spring 的 API。無疑,第一種方法是我們的最佳選擇。
init-method
的功能和InitializingBean
接口一樣。它定義了一個(gè) Bean 的初始化方法,在 Bean 的所有屬性設(shè)置完成之后自動(dòng)調(diào)用。這個(gè)初始化方法不用依賴于 Spring 的任何 API。它必須是一個(gè)無參數(shù)的方法,可以拋出 Exception。
例如:我們的 Bean 組件UserManger
中定義一個(gè)初始化方法init()
。這樣,我們就可以在 Bean 定義時(shí)指定這個(gè)初始化方法:
<bean id=”userManger” class=”com.dev.spring.um.DefaultUserManager”
init-method=”init”>
……
</bean>
Bean 完成所有的之前初始化之后,就進(jìn)入了準(zhǔn)備就緒(Ready)狀態(tài)。這就意味著你的應(yīng)用程序可以取得這些 Bean,并根據(jù)需要使用他們。