該篇部落客要闡述關于Bean的作用域(scope)。Spring容器最初提供了兩種bean的scope類型:singleton和prototype,在Spring2.0之後又引入了另外三種scope類型:request、session、global session類型。不過這三種類型有所限制:隻能在Web應用中使用。也就是說,隻有Web應用的ApplicationContext中使用這三個scope才合理,類似如下代碼來進行使用
當然很多書是将scope翻譯為作用域,但是筆者比較喜歡《Spring揭秘》上對scope的解釋“scope用來聲明容器中的對象所應該處的限定場景或者說該對象的存活時間,即容器在對象進入其相應的scope之前生成并裝配這些對象,在該對象不再處于這些scope的限定之後,容器通常會銷毀這些對象”
舉個例子:比如我們都處在社會(容器)中,如果把中學教師作為一個類定義,那麼當容器初始化這些類之後,中學教師隻能局限在中學這樣的場景,中學就可以看作中學老師的scope
<bean id="beanname" class="com.linjie.Bean" scope="prototype"/>
該篇部落客要闡述
1、singleton
2、prototype
3、request、session、global session(介紹)

一、singleton(單例)
singleton是容器預設的scope,是以寫和不寫沒有差別。scope為singleton的時候,在Spring的IoC容器中隻存在一個執行個體,所有對該對象的引用将共享這個執行個體。該執行個體從容器啟動,并因為第一次被請求而初始化後,将一直存活到容器退出,也就是說,它與IoC容器“幾乎”擁有相同的壽命
singleton的bean具有的特性
- 對象執行個體數量:singleton類型的bean定義,在一個容器中隻存在一個共享執行個體,所有對該類型bean的依賴都引用這一單一執行個體
- 對象存活時間:singleton類型bean定義,從容器啟動,到它第一次被請求而執行個體化開始,隻要容器不銷毀或退出,該類型的單一執行個體就會一直存活
可以看下面的Demo(scope為singleton)
SingletonBean.java
package com.linjie.scope;
public class SingletonBean {
/*
* 無參構造方法
*/
public SingletonBean() {
System.out.println("SingletonBean初始化");
}
}
測試類
package com.linjie.scope;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SingletonTest {
@Test
public void test() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
SingletonBean singletonbean1 = (SingletonBean) context.getBean("singletonbean");
SingletonBean singletonbean2 = (SingletonBean) context.getBean("singletonbean");
System.out.println(singletonbean1);
System.out.println(singletonbean2);
}
}
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="singletonbean" class="com.linjie.scope.SingletonBean" scope="singleton"/>
</beans>
結果
可以看到顯示結果,SingletonBean隻初始化了一次,并且列印出來的結果也是一樣的
二、prototype(多例)
對于那些請求方不能共享的對象執行個體,應該将其bean定義的scope設定為prototype。這樣,每個請求方可以得到自己對應的一個對象執行個體。通常,聲明為prototype的scope的bean定義類型,都是一些有狀态的,比如儲存每個顧客資訊的對象
可以看下面的Demo(scope為prototype)
PrototypeBean.java
package com.linjie.scope;
public class PrototypeBean {
public PrototypeBean() {
System.out.println("Prototype:初始化");
}
}
測試類
package com.linjie.scope;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class PrototypeTest {
@Test
public void test() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
PrototypeBean prototypebean1 = (PrototypeBean) context.getBean("prototypebean");
PrototypeBean prototypebean2 = (PrototypeBean) context.getBean("prototypebean");
System.out.println(prototypebean1);
System.out.println(prototypebean2);
}
}
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="prototypebean" class="com.linjie.scope.PrototypeBean" scope="prototype"/>
</beans>
結果
可以看到顯示結果,PrototypeBean初始化了兩次,并且每次列印出來的值也是不一樣的
三、request、session、global session(介紹)
這三個scope類型是Spring2.0之後新增加的,它們不像上面兩個那麼通用,它們隻适用于Web應用程式,通常是與XmlWebApplicationContext共同使用(注意:隻能使用scope屬性才能使用這三種,也就是必須使用XSD文檔聲明的XML配置檔案格式)
1、request
在Spring容器中,即XmlWebApplicationContext會為每個HTTP請求建立一個全新的Request-Processor對象供目前請求使用,當請求結束後,該對象實生命周期就結束。當同時有10個HTTP請求進來的時候,容器會分别針對這10個請求傳回10個全新的RequestProcessor對象執行個體,且它們之間互不幹擾。是以嚴格意義上說request可以看作prototype的一種特例,除了request的場景更加具體
<bean id="requestProcessor" class="......" scope="request"/>
2、session
放到session中的最普遍的資訊就是使用者登入資訊,Spring容器會為每個獨立的session建立屬于它們自己全新的UserPreferences對象執行個體。與request相比,除了擁有session scope的bean比request scope的bean可能更長的存活時間,其他沒什麼差别
<bean id="sessionProcessor" class="......" scope="session"/>
3、global session
global session隻有應用在基于portlet的Web應用程式中才有意義,它映射到portlet的global範圍的session。如果在普通的基于servlet的Web應用中使了用這個類型的scope,容器會将其作為普通的session類型的scope來對待
什麼是portlet
Portlets是一種Web元件-就像servlets-是專為将合成頁面裡的内容聚集在一起而設計的。通常請求一個portal頁面會引發多個portlets被調用。每個portlet都會生成标記段,并與别的portlets生成的标記段組合在一起嵌入到portal頁面的标記内。
參考
《Spring揭秘》
《Spring IN ACTION》