spring詳解(二)

容器中bean的作用域

|作用域|描述|
|---|---|
|singleton|單例模式各淀,在整個Spring IoC容器中,使用singleton定義的bean將只有一個實例|
|prototype|原型模式诡挂,每次通過容器的getBean方法獲取prototype定義的Bean時碎浇,都將產(chǎn)生一個新實例|
|request|對于每次HTTP請求中,使用request定義的bean都將產(chǎn)生一個新實例璃俗,只有在web應(yīng)用程序使用Spring時奴璃,該作用域才有效|
|session|同理|
|global session|同理|

注意request和session作用域只在web應(yīng)用中才生效,并且必須在web應(yīng)用中增加額外的配置才會生效城豁,為了讓request苟穆,session兩個作用域生效,必須將HTTP請求對象綁定到為該請求提供服務(wù)的線程上,這使得具有request和session作用域的Bean實例能夠在后面的調(diào)用鏈中被訪問雳旅。

當(dāng)支持Servlet2.4及以上規(guī)范的web容器時跟磨,我們可以在web應(yīng)用的web.xml增加如下Listener配置,該Listener負責(zé)為request作用域生效:

<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>

 如果僅使用了支持Servlet2.4以前規(guī)范的web容器攒盈,則該容器不支持Listener規(guī)范抵拘,故無法使用這種配置,可以使用Filter配置方式沦童,我們可以在web應(yīng)用的web.xml增加如下Filter配置:

<filter>
<filter-name>requestContextFilter</filter-name>
<filter-class>org.springframework.web.filter.RequestContextFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>requestContextFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

再如下面的代碼:

<bean id="p" class="lee.Person" scope="request"/>

`這樣容器就會為每次HTTP請求生成一個lee.Person的實例當(dāng)該請求響應(yīng)結(jié)束時仑濒,該實例也隨之消失。`
`如果Web應(yīng)用直接使用Spring MVC作為MVC框架偷遗,即使用`SpringDispatchServlet`或`DispatchPortlet`來攔截所有用戶請求墩瞳,則`無需這些額外的配置`,`因為SpringDispatchServlet或DispatchPortlet已經(jīng)處理了所有和請求有關(guān)的狀態(tài)處理`氏豌。`

④**獲取容器的引用**:

>`通常情況下:`
Bean無需訪問Spring容器喉酌,而是通過Spring容器訪問的,即使 需要手動訪問Spring容器泵喘,程序也已通過類似下面的代碼獲取Spring容器 的引用泪电。

ApllicationContext cts = ClassPathApplalicationContext("bean.xml");

`但在一些極端的情況下`,可能Bean需要訪問Spring容器纪铺。Spring提供另一種方法訪問Spring容器:

>實現(xiàn)BeanFactoryAware接口的Bean相速,擁有訪問Spring容器的能力,實現(xiàn)BeanFactoryAware的Bean被容器實例化后鲜锚,會擁有一個引用指向創(chuàng)建他的BeanFactory突诬。BeanFactoryAware只有一個方法setBeanFactory(BeanFactory beanFactory)該參數(shù)指向創(chuàng)建他的BeanFactory。

>`缺點`:污染了代碼芜繁,使代碼與Spring接口耦合在一起旺隙,因此沒有特別的必要,建議不要直接訪問容器骏令。

---
4.**Bean實例的創(chuàng)建方式及對應(yīng)配置**:

>創(chuàng)建Bean的方法:
<li>調(diào)用構(gòu)造器創(chuàng)建Bean實例蔬捷;
<li>調(diào)用靜態(tài)工廠方法創(chuàng)建Bean;
<li>調(diào)用實例工廠創(chuàng)建Bean榔袋。

**調(diào)用靜態(tài)工廠方法創(chuàng)建Bean**:

>使用靜態(tài)工廠方法創(chuàng)建Bean實例時周拐,class屬性也必須指定,但此時class屬性并不是指定Bean實例的實現(xiàn)類凰兑,而是靜態(tài)工廠類速妖。因為Spring需要知道是用哪個工廠來創(chuàng)建Bean實例。另外聪黎,還需要使用factory-method來指定靜態(tài)工廠方法名,Spring將調(diào)用靜態(tài)工廠方法(可能包含一組參數(shù)),來返回一個Bean實例稿饰,一旦獲得了指定Bean實例锦秒,Spring后面的處理步驟與采用普通方法創(chuàng)建Bean實例則完全一樣。需要注意的是喉镰,當(dāng)使用靜態(tài)工廠方法來創(chuàng)建Bean時旅择,這個factory-method必須要是靜態(tài)的。這段闡述聽上去有點暈侣姆,話不多說生真,上代碼:
`先定義一個接口,靜態(tài)方法產(chǎn)生的將是該接口的實例:`

public interface Animal {
public void sayHello();
}

`下面是接口的兩個實現(xiàn)類:`

public class Cat implements Animal {
private String msg;
//依賴注入時必須的setter方法
public void setMsg(String msg){
this.msg = msg;
}
@Override
public void sayHello(){
System.out.println(msg + "捺宗,喵");
}
}

public class Dog implements Animal {
private String msg;
//依賴注入時必須的setter方法
public void setMsg(String msg){
this.msg = msg;
}
@Override
public void sayHello(){
System.out.println(msg + "柱蟀,旺");
}
}

`下面的AnimalFactory工廠中包含了一個getAnimal的靜態(tài)方法,該方法將根據(jù)傳入的參數(shù)決定創(chuàng)建哪個對象蚜厉。這是`典型的靜態(tài)工廠設(shè)計模式`长已。`

public class AnimalFactory {
public static Animal getAnimal(String type){
if ("cat".equalsIgnoreCase(type)){
return new Cat();
} else {
return new Dog();
}
}
}

`如果需要指定Spring使用AnimalFactory來產(chǎn)生Animal對象,則可在Spring配置文件中作如下配置:`


<bean id="cat" class="com.abc.AnimalFactory" factory-method="getAnimal">

<constructor-arg value="cat" />

<property name="msg" value="貓貓" />
</bean>

<bean id="dog" class="com.abc.AnimalFactory" factory-method="getAnimal">

<constructor-arg value="dog" />

<property name="msg" value="狗狗" />
</bean>

`從上面的配置可以看出:cat和dog兩個Bean配置的class和factory-method完全相同昼牛,這是因為兩個實例都使用同一個靜態(tài)工廠類术瓮、同一個靜態(tài)工廠方法產(chǎn)生得到的。只是為這個靜態(tài)工廠方法指定的參數(shù)不同贰健,使用<constructor-arg />元素來為靜態(tài)工廠方法指定參數(shù)胞四。`
主程序獲取cat和dog兩個Bean實例的方法不變,同樣只需要調(diào)用Spring容器的getBean()即可:

public class Test {
public static void main(String args[]){
ApplicationContext context =
new ClassPathXmlApplicationContext("applicationContext.xml");
Animal a1 = context.getBean("cat", Animal.class);
a1.sayHello();
Animal a2 = context.getBean("dog", Animal.class);
a2.sayHello();
}
}

輸出結(jié)果:

貓貓伶椿,喵
狗狗辜伟,旺

使用靜態(tài)工廠方法創(chuàng)建實例時必須提供工廠類和產(chǎn)生實例的靜態(tài)工廠方法。通過靜態(tài)工廠方法創(chuàng)建實例時需要對Spring配置文件做如下改變:
<li>`class屬性不在是Bean實例的實現(xiàn)類悬垃,而是生成Bean實例的靜態(tài)工廠類`

><li>`使用factory-method指定生產(chǎn)Bean實例的靜態(tài)工廠方法`

><li>`如果靜態(tài)工廠方法需要參數(shù)游昼,使用<constructor-arg />元素為其配置`
`當(dāng)我們指定Spring使用靜態(tài)工廠方法來創(chuàng)建Bean實例時,Spring將`先解析配置文件`尝蠕,并根據(jù)配置文件指定的信息烘豌,通過`反射調(diào)用靜態(tài)工廠類的靜態(tài)工廠方法`,并將該靜態(tài)工廠方法的返回值作為Bean實例看彼,在這個過程中廊佩,`Spring不再負責(zé)創(chuàng)建Bean實例`,Bean實例是由用戶提供的靜態(tài)工廠方法提供的靖榕。`

---
**調(diào)用實例工廠方法創(chuàng)建Bean**:

>實例工廠方法與靜態(tài)工廠方法只有一點不同:調(diào)用靜態(tài)工廠方法只需要使用工廠類即可标锄,調(diào)用實例工廠方法則必須使用工廠實例。所以在Spring配置上也只有一點區(qū)別:配置靜態(tài)工廠方法指定靜態(tài)工廠類茁计,配置實例工廠方法則指定工廠實例料皇。
`同樣是上面的例子將AnimalFactory修改為:`

public clas AnimalFactory {
public Animal getAnimal(String type){ //這里僅僅是去掉了static關(guān)鍵字
if ("cat".equalsIgnoreCase(type)){
return new Cat();
} else {
return new Dog();
}
}
}

`Spring文件修改為:`


<bean id="animalFactory" class="com.abc.AnimalFactory" />

<bean id="cat" factory-bean="animalFactory" factory-method="getAnimal">

<constructor-arg value="cat" />
<property name="msg" value="貓貓" />
</bean>
<bean id="dog" factory-bean="animalFactory" factory-method="getAnimal">
<constructor-arg value="dog" />
<property name="msg" value="狗狗" />
</bean>

測試類不用修改,輸出結(jié)果和上面相同。

---

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末践剂,一起剝皮案震驚了整個濱河市鬼譬,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌逊脯,老刑警劉巖优质,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異军洼,居然都是意外死亡巩螃,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進店門匕争,熙熙樓的掌柜王于貴愁眉苦臉地迎上來避乏,“玉大人,你說我怎么就攤上這事汗捡∈缂剩” “怎么了?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵扇住,是天一觀的道長春缕。 經(jīng)常有香客問我,道長艘蹋,這世上最難降的妖魔是什么锄贼? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮女阀,結(jié)果婚禮上宅荤,老公的妹妹穿的比我還像新娘。我一直安慰自己浸策,他們只是感情好冯键,可當(dāng)我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著庸汗,像睡著了一般惫确。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蚯舱,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天改化,我揣著相機與錄音,去河邊找鬼枉昏。 笑死陈肛,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的兄裂。 我是一名探鬼主播句旱,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼阳藻,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了前翎?” 一聲冷哼從身側(cè)響起稚配,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎港华,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體午衰,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡立宜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了臊岸。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片橙数。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖帅戒,靈堂內(nèi)的尸體忽然破棺而出灯帮,到底是詐尸還是另有隱情,我是刑警寧澤逻住,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布钟哥,位于F島的核電站,受9級特大地震影響瞎访,放射性物質(zhì)發(fā)生泄漏腻贰。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一扒秸、第九天 我趴在偏房一處隱蔽的房頂上張望播演。 院中可真熱鬧,春花似錦伴奥、人聲如沸写烤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽洲炊。三九已至,卻和暖如春锣吼,著一層夾襖步出監(jiān)牢的瞬間选浑,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工玄叠, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留古徒,地道東北人。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓读恃,卻偏偏與公主長得像隧膘,于是被迫代替她去往敵國和親代态。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內(nèi)容