個(gè)人獨立域名博客開(kāi)通啦,歡迎大家訪(fǎng)問(wèn):http://www.mzone.cc
上次簡(jiǎn)單的說(shuō)了下spring的IOC,也說(shuō)到了spring的IOC強大在于有一系列可以維護Bean不同關(guān)系的維護類(lèi)的存在,而這樣的維護也是基于高度可配置的spring配置文件而言的。這次就是結合我的使用spring的IOC來(lái)講講我在使用中的體會(huì ),當然,這里涉及的內容不會(huì )很高深,但是也必須讀者能夠讀懂簡(jiǎn)單的Bean配置才可以。
我們這里只講spring的IOC,AOP不在這范圍之內,雖然AOP也是基于IOC之上的,至于那些集合啊什么的配置也不是這里的重點(diǎn)。我們這里說(shuō)spring的Bean配置,主要就是說(shuō)如何配置Bean在配置文件中,可以使結構更加合理化和使我們的編寫(xiě)量更少,當然我所說(shuō)的也不一定對,也是和大家一起討論討論:),也希望大家可以提出更好的方法或模式。
在spring的Bean配置中總的來(lái)說(shuō)其實(shí)就一個(gè)標簽<bean></bean>,這個(gè)bean標簽就攘括了幾乎所有的配置,然后bean的繼承、抽象等都是基于此標簽之上的,掌握了bean的配置,詳細可以使自己有一個(gè)比較大的提升,尤其是對于新手來(lái)說(shuō)(我也是,呵呵

<bean id="bean_test" class="cn.qtone.test.HelloWorld"></bean>
這里我們就簡(jiǎn)單的使用HelloWorld類(lèi)來(lái)實(shí)例化,使用默認的構造方法,即相當于我們使用:
HelloWorld tmp = new HelloWorld();
但有一點(diǎn)不同的是在spring配置中的在整個(gè)應用期間只有一個(gè)實(shí)例,即是單例的,當然這個(gè)單例是指對一個(gè)IOC容器(spring)來(lái)說(shuō)的,而不是我們通常說(shuō)說(shuō)的單態(tài)模式。當然,spring也可以這樣配置不是單態(tài)的實(shí)例,比如我們修改如下:
<bean id="bean_test" class="cn.qtone.test.HelloWorld" scope="prototype"></bean>
注意其中的不同顏色部分,這樣配置后就表明每次從spring容器中獲取HelloWorld的實(shí)例的時(shí)候就會(huì )new一個(gè)新對象,即我們所說(shuō)的原型,spring中scope默認的是單態(tài)(singleton),當然針對web應用程序,還可以配置為request、session等范圍。至于什么時(shí)候使用什么權限范圍就要看應用程序的使用了,比如在多線(xiàn)程程序中,單態(tài)是否會(huì )對程序有所影響就需要考慮了。
如果HelloWorld類(lèi)沒(méi)有空的構造方法,只有如下的兩個(gè)構造方法,那我們該如何配置呢?
……
public HelloWorld(String str)
{
……
}
public HelloWorld(Date date, int i)
{
……
}
……
由于沒(méi)有默認構造方法,所以我們就需要在bean的配置中寫(xiě)上構造參數才可以,如下:
<!-- 使用一個(gè)參數的構造 -->
<bean id="bean_test" class="cn.qtone.test.HelloWorld" scope="prototype">
<constructor-arg><value>hello</value></constructor-arg>
</bean>
上面說(shuō)的使用一個(gè)參數的,即帶字符串參數的構造方法,如果想使用帶日期和整型的構造方法,那么就要做如下的配置了:
<bean id="bean_date" class="java.util.Date" />
<!-- 使用二個(gè)參數的構造 -->
<bean id="bean_test" class="cn.qtone.test.HelloWorld" scope="prototype">
<constructor-arg ref="bean_date"></constructor-arg>
<constructor-arg><value>345</value></constructor-arg>
</bean>
注意到上面的配置中我們使用了ref關(guān)鍵字,這個(gè)是表示引用配置文件中的ID為bean_date的對象,另外對于類(lèi)型,spring會(huì )做恰當的轉換,比如將345轉換成數字等。當然,這樣對簡(jiǎn)單的構造來(lái)說(shuō)不會(huì )有什么問(wèn)題,如果情況比較復雜的話(huà),那么一般建議使用序號來(lái)標定,如下:
<!-- 使用二個(gè)參數的構造 -->
<bean id="bean_test" class="cn.qtone.test.HelloWorld" scope="prototype">
<constructor-arg index="0" ref="bean_date"></constructor-arg>
<constructor-arg index="1"><value>345</value></constructor-arg>
</bean>
這樣,使用index屬性表示該參數所在位置了后,無(wú)論是spring構造起來(lái),還是我們查看都會(huì )很方便。當然,spring也提供了自動(dòng)查找,也就是依賴(lài)查找的功能,但是這個(gè)我覺(jué)得大家還是少用,因為這樣會(huì )使整個(gè)配置文件看起來(lái)非常的不直觀(guān),而且不清晰,說(shuō)不定過(guò)了一段時(shí)間再去看的時(shí)候就不知道是什么意思了,在正式應用項目中,還是將各個(gè)bean的關(guān)系進(jìn)行組織和編寫(xiě)清楚為好。
上面所說(shuō)的都是構造來(lái)實(shí)例化一個(gè)bean,但有時(shí)候我們都會(huì )使用工廠(chǎng)模式來(lái)獲取bean。對于工廠(chǎng)模式,我們一般也使用靜態(tài)工廠(chǎng)模式和實(shí)例工廠(chǎng)模式,這兩個(gè)在spring中配置也是不太一樣的。對于靜態(tài)工廠(chǎng)模式來(lái)實(shí)例化bean的,我們的配置如下:
<bean id="bean_string" class="cn.qtone.test.TestFactory" factory-method="getBean"/>
當然,我們也可以為靜態(tài)工廠(chǎng)模式的bean來(lái)使用構造參數,這個(gè)就不說(shuō)了。我們上面的bean配置對應的實(shí)際代碼就應該是:
……
public static Object getBean()
{
return "hello world";
}
……
那么spring在實(shí)例化ID為bean_string的bean時(shí),就會(huì )使用TestFactory的getBean()方法來(lái)獲取,而且TestFactory是沒(méi)有被實(shí)例化的,即是使用靜態(tài)方法來(lái)獲取的。對于實(shí)例工廠(chǎng)模式的話(huà),我們的配置和上面就稍微有點(diǎn)不一樣了,那我們就應該配置兩個(gè)bean, 一個(gè)是實(shí)例的工廠(chǎng)bean,還一個(gè)就是我們要獲取的bean的配置了,如下:
<bean id="bean_factory" class="cn.qtone.test.TestBeanFactory"/>
<bean id="bean_helloWorld" factory-bean="bean_factory" factory-method="getHello"/>
上面的配置中,spring容器將首先實(shí)例化一個(gè)TestBeanFactory,然后再根據該類(lèi)的方法getHello來(lái)獲取一個(gè)bean的實(shí)例,我們這里以HelloWorld對象為例,對應的代碼就應該如下:
……
public HelloWorld getHello()
{
return new HelloWorld();
}
……
注意到,我們這里的getHello方法并不是靜態(tài)方法,而是實(shí)例方法,所以必須先實(shí)例化TestBeanFactory后才能夠調用。
上面說(shuō)的都是如何去實(shí)例化一個(gè)bean,沒(méi)有說(shuō)到bean的屬性注入。雖然我們也可以通過(guò)構造的時(shí)候進(jìn)行一次注入,但這樣做不僅失去了靈活性,而且一長(cháng)串的構造參數看著(zhù)也眼疼哈,呵呵。當然,有一種情況下,我們是應該使用構造注入的,就是希望注入的對象不能夠被外界修改時(shí),我們這時(shí)候就必須使用構造注入了。對于bean的屬性注入,以HelloWorld為例,我們可以簡(jiǎn)單的配置如下:
<bean id="bean_test" class="cn.qtone.test.HelloWorld">
<property name="hello" value="你好!" />
<property name="world" value="世界" />
<property name="date" ref="bean_date" />
</bean>
上面的配置中使用了三個(gè)屬性注入,即spring中的setter注入方式。注意第三個(gè)屬性,使用了ref,表明這個(gè)date屬性的設置參數是關(guān)聯(lián)到ID為bean_date的bean上去的。注意在使用setter注入的時(shí)候,屬性的名稱(chēng)不是方法的全名稱(chēng),而是滿(mǎn)足javaBean規范的命名方式,即如果屬性名稱(chēng)為xxx,那么其對應的方法名稱(chēng)就應該是:setXxx(),注意的是除了xxx中第一個(gè)字符不區分大小寫(xiě)之外,其他的是要嚴格區分的。那么對照上面的配置,我們的HelloWorld的方法就應該如下:
……
public void setHello(String hello)
{
……
}
public void setWorld(String world)
{
……
}
public void setDate(Date date)
{
……
}
……
使用setter注入的好處就是可以很清晰的知道每一個(gè)注入的是什么參數和意義,通過(guò)名稱(chēng)就可以很容易的看出來(lái),這也是spring提倡使用setter注入的原因之一。
今天就簡(jiǎn)單的說(shuō)下spring的bean的基礎配置,包括bean的實(shí)例化和屬性的注入等。下次就講下配置中的bean的繼承、抽象等話(huà)題。也歡迎和大家一起交流討論:)
聯(lián)系客服