【跟我學spring 4.0 】之第六節-spring中scope作用域

Spring Framework支持五種作用域(其中有三種只能用在基於web的SpringApplicationContext)。

singleton

在每個Spring IoC容器中一個bean定義對應一個對象實例。

prototype

一個bean定義對應多個對象實例。

request

在一次HTTP請求中,一個bean定義對應一個實例;即每次HTTP請求將會有各自的bean實例,它們依據某個bean定義創建而成。該作用域僅在基於web的Spring ApplicationContext情形下有效。

session

在一個HTTP Session中,一個bean定義對應一個實例。該作用域僅在基於web的Spring ApplicationContext情形下有效。

global session

在一個全局的HTTP Session中,一個bean定義對應一個實例。典型情況下,僅在使用portlet context的時候有效。該作用域僅在基於web的Spring ApplicationContext情形下有效。


1.Singleton作用域

當一個bean的作用域爲singleton, 那麼Spring IoC容器中只會存在一個共享的bean實例,並且所有對bean的請求,只要id與該bean定義相匹配,則只會返回bean的同一實例。

換言之,當把一個bean定義設置爲singlton作用域時,Spring IoC容器只會創建該bean定義的唯一實例。這個單一實例會被存儲到單例緩存(singleton cache)中,並且所有針對該bean的後續請求和引用都將返回被緩存的對象實例。 

Singleton作用域是Spring中的缺省作用域。即默認值!!!

<pre name="code" class="html"><bean id="role" class="spring.chapter2.maryGame.Role" scope="singleton"/>
或者
<bean id="role" class="spring.chapter2.maryGame.Role" singleton="true"/>

2.Prototype

Prototype作用域的bean會導致在每次對該bean請求(將其注入到另一個bean中,或者以程序的方式調用容器的getBean()方法)時都會創建一個新的bean實例。根據經驗,對所有有狀態的bean應該使用prototype作用域,而對無狀態的bean則應該使用singleton作用域。

請注意,典型情況下,DAO不會被配置成prototype,因爲一個典型的DAO不會持有任何會話狀態,因此應該使用singleton作用域。

對於prototype作用域的bean,有一點非常重要,那就是Spring不能對一個prototype bean的整個生命週期負責:容器在初始化、配置、裝飾或者是裝配完一個prototype實例後,將它交給客戶端,隨後就對該prototype實例不聞不問了。不管何種作用域,容器都會調用所有對象的初始化生命週期回調方法,而對prototype而言,任何配置好的析構生命週期回調方法都將不會被調用。清除prototype作用域的對象並釋放任何prototype bean所持有的昂貴資源,都是客戶端代碼的職責。(讓Spring容器釋放被singleton作用域bean佔用資源的一種可行方式是,通過使用bean的後置處理器,該處理器持有要被清除的bean的引用。)

談及prototype作用域的bean時,在某些方面你可以將Spring容器的角色看作是Java new操作符的替代者。任何遲於該時間點的生命週期事宜都得交由客戶端來處理。在Section 3.5.1, “Lifecycle接口”一節中會進一步講述Spring IoC容器中的bean生命週期。

 

向後兼容性:在XML中指定生命週期作用域

如果你在bean定義文件中引用'spring-beans.dtd' DTD,要顯式說明bean的生命週期作用域你必須使用"singleton"屬性(記住singleton生命週期作用域是默認的)。 如果引用的是'spring-beans-2.0.dtd' DTD或者是Spring 2.0 XSD schema,那麼需要使用"scope"屬性(因爲"singleton"屬性被刪除了,新的DTDXSD文件使用"scope"屬性)

簡單地說,如果你用"singleton"屬性那麼就必須在那個文件裏引用'spring-beans.dtd' DTD。 如果你用"scope"屬性那麼必須 在那個文件裏引用'spring-beans-2.0.dtd' DTD 'spring-beans-2.0.xsd' XSD

配置實例: 

<bean id="role" class="spring.chapter2.maryGame.Role" scope="prototype"/>
或者
<beanid="role" class="spring.chapter2.maryGame.Role" singleton="false"/>


3. 其他作用域

其他作用域,即requestsession以及global session僅在基於web的應用中使用(不必關心你所採用的是什麼web應用框架)。

Note

下面介紹的作用域僅僅在使用基於webSpring ApplicationContext實現(如XmlWebApplicationContext)時有用。如果在普通的Spring IoC容器中,比如像XmlBeanFactoryClassPathXmlApplicationContext,嘗試使用這些作用域,你將會得到一個IllegalStateException異常(未知的bean作用域)。

3.1. 初始化web配置

要使用requestsession和 global session作用域的bean(即具有web作用域的bean),在開始設置bean定義之前,還要做少量的初始配置。請注意,假如你只想要“常規的”作用域,也就是singletonprototype,就不需要這一額外的設置。

在目前的情況下,根據你的特定servlet環境,有多種方法來完成這一初始設置。如果你使用的是Servlet 2.4及以上的web容器,那麼你僅需要在web應用的XML聲明文件web.xml中增加下述ContextListener即可

org.springframework.web.context.request.RequestContextListener

即:

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


如果你用的是早期版本的web容器(Servlet 2.4以前),那麼你要使用一個javax.servlet.Filter的實現。請看下面的web.xml配置片段:

requestContextFilter

org.springframework.web.filter.RequestContextFilter

requestContextFilter

/*

即:

<web-app>
 ..
 <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>
   ...
</web-app>


3.2. Request作用域

考慮下面bean定義:

針對每次HTTP請求,Spring容器會根據loginAction bean定義創建一個全新的LoginAction bean實例,且該loginAction bean實例僅在當前HTTP request內有效,因此可以根據需要放心的更改所建實例的內部狀態,而其他請求中根據loginAction bean定義創建的實例,將不會看到這些特定於某個請求的狀態變化。當處理請求結束,request作用域的bean實例將被銷燬。

<bean id="role" class="spring.chapter2.maryGame.Role" scope="request"/>


3.3. Session作用域

考慮下面bean定義:

針對某個HTTP SessionSpring容器會根據userPreferences bean定義創建一個全新的userPreferences bean實例,且該userPreferences bean僅在當前HTTP Session內有效。與request作用域一樣,你可以根據需要放心的更改所創建實例的內部狀態,而別的HTTP Session中根據userPreferences創建的實例,將不會看到這些特定於某個HTTP Session的狀態變化。當HTTP Session最終被廢棄的時候,在該HTTP Session作用域內的bean也會被廢棄掉。

<bean id="role" class="spring.chapter2.maryGame.Role" scope="session"/>

3.4. global session作用域

考慮下面bean定義:

global session作用域類似於標準的HTTP Session作用域,不過它僅僅在基於portletweb應用中才有意義。Portlet規範定義了全局Session的概念,它被所有構成某個portlet web應用的各種不同的portlet所共享。在global session作用域中定義的bean被限定於全局portlet Session的生命週期範圍內。

請注意,假如你在編寫一個標準的基於Servletweb應用,並且定義了一個或多個具有global session作用域的bean,系統會使用標準的HTTP Session作用域,並且不會引起任何錯誤。

<bean id="role" class="spring.chapter2.maryGame.Role" scope="global session"/>

3.5. 作用域bean與依賴

能夠在HTTP request或者Session(甚至自定義)作用域中定義bean固然很好,但是Spring IoC容器除了管理對象(bean)的實例化,同時還負責協作者(或者叫依賴)的實例化。如果你打算將一個Http request範圍的bean注入到另一個bean中,那麼需要注入一個AOP代理來替代被注入的作用域bean。也就是說,你需要注入一個代理對象,該對象具有與被代理對象一樣的公共接口,而容器則可以足夠智能的從相關作用域中(比如一個HTTP request)獲取到真實的目標對象,並把方法調用委派給實際的對象。

 

不能和作用域爲singletonprototypebean一起使用。爲singleton bean創建一個scoped proxy將拋出BeanCreationException異常。

 4.引入簡單singleton實例:

配置文件:spring-relation.xml

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:util="http://www.springframework.org/schema/util" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"
	default-autowire="byName" default-lazy-init="true">
	<!-- 使用bean的scope屬性來配置bean的作用域
		singleton:默認值,容器初始化時創建bean實例,在整個容器的生命週期內只創建這一個bean,單例的
		prototype:一個bean定義對應多個對象實例。
		request:在一次HTTP請求中,一個bean定義對應一個實例;即每次HTTP請求將會有各自的bean實例,它們依據某個bean定義創建而成。該作用域僅在基於web的Spring ApplicationContext情形下有效。
		session:在一個HTTP Session中,一個bean定義對應一個實例。該作用域僅在基於web的Spring ApplicationContext情形下有效。f
		global session:在一個全局的HTTP Session中,一個bean定義對應一個實例。典型情況下,僅在使用portlet context的時候有效。該作用域僅在基於web的Spring ApplicationContext情形下有效。 -->
	
	<bean id="car" scope="singleton"  class="com.zd.runsharing.maven.springAutowire.Car">
	<property name="brand" value="寶馬啊汽車品牌"></property>
	<property name="price" value="43000000"></property>
	</bean>
	
	</beans>

Car類:

public class Car {
	public Car() {
		System.out.println("Car .. constractor....");
	}
	private String brand;
	private double price;
	public String getBrand() {
		return brand;
	}
	public void setBrand(String brand) {
		this.brand = brand;
	}
	public double getPrice() {
		return price;
	}
	public void setPrice(double price) {
		this.price = price;
	}
	@Override
	public String toString() {
		return "Car [brand=" + brand + ", price=" + price + "]";
	}
	

}
主函數測試類:

public class BeanRelationMainTest {

	public static void main(String[] args) {
		 ApplicationContext atx = new ClassPathXmlApplicationContext("spring-relation.xml");
		 
		 
		 Car  car = (Car) atx.getBean("car");
		 Car  car2 = (Car) atx.getBean("car");
		 System.out.println(car == car2);
	}

}

運行結果:


=================================================================================

=================================================================================

=================================================================================



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章