在配置文件裏聲明的Bean時,實際定義的並不是一個Bean實例,而是爲Bean創建了一個模板,當通過getBean()調用或其他請求改Bean的時候,Spring將根據Bean的實際作用域返回Bean的實例,在某些情況下默認的作用域並不適合,此時需要爲Bean設置一個更適合的作用域。在Spring2.x裏,可以通過<bean>中的scope屬性設置作用域,默認情況下Spring只爲在Ioc容器裏聲明的Bean創建一個實例,整個Ioc範圍內都共享這個實例,所有後續的getBean()調用和引用該實例,都將返回這個唯一的Bean實例。這個作用域稱爲singleton,是默認的作用域。
Spring2.x中Bean的幾種作用域:
1、singleton--------------爲每個Spring Ioc容器創建一個Bean實例;
2、prototype-------------每次請求時都創建一個新的實例;
3、request---------------每個HTTP請求創建一個Bean實例,這個作用域僅在WEB應用程序的上下文中有效;
4、session---------------每個HTTP請求創建一個Bean實例,這個作用域僅在WEB應用程序的上下文中有效;
5、globalSession------爲每個全局的HTTP會話創建一個Bean實例,這個作用域盡在門戶應用程序的上下文中有效;
下邊將用一個商品購物車例子來說明這個Bean的實例作用域:
package com.song.spring.scope; public abstract class Product { private String name; private double price; public Product(){} public Product(String name, double price){ this.name = name; this.price = price; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } public String toString(){ return name + " " + price; } }
package com.song.spring.scope;
public class Battery extends Product {
private boolean rechargeable;
public Battery(){
super();
}
public Battery(String name, double price){
super(name, price);
}
public boolean isRechargeable() {
return rechargeable;
}
public void setRechargeable(boolean rechargeable) {
this.rechargeable = rechargeable;
}
}
package com.song.spring.scope;
public class Disc extends Product {
private int capacity;
public Disc(){
super();
}
public Disc(String name, double price){
super(name, price);
}
public int getCapacity() {
return capacity;
}
public void setCapacity(int capacity) {
this.capacity = capacity;
}
}
接下來創建一個無購物車實例;
package com.song.spring.scope;
import java.util.ArrayList;
import java.util.List;
public class ShoppingCart {
private List<Product> items = new ArrayList<Product>();
public void addItem(Product item){
items.add(item);
}
public List<Product> getItem(){
return items;
}
}
在classpath:下的xml文件applicationContext.xml中的Bean配置爲:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN"
"http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
<bean id="aaa" class="com.song.spring.scope.Battery">
<property name="name" value="AAA" />
<property name="price" value="2.5" />
</bean>
<bean id="cdrw" class="com.song.spring.scope.Disc">
<property name="name" value="CD-RW" />
<property name="price" value="1.5" />
</bean>
<bean id="dvdrw" class="com.song.spring.scope.Disc">
<property name="name" value="DVD-RW" />
<property name="price" value="3.0" />
</bean>
<bean id="shoppingCart" class="com.song.spring.scope.ShoppingCart" />
</beans>
創建一個運行類:
package com.song.spring.scope;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Product aaa = (Product)context.getBean("aaa");
Product cdrw = (Product)context.getBean("cdrw");
Product dvdrw = (Product)context.getBean("dvdrw");
ShoppingCart cart1 = (ShoppingCart)context.getBean("shoppingCart");
cart1.addItem(aaa);
cart1.addItem(cdrw);
System.out.println("Shopping Cart1 contains:" + cart1.getItem());
ShoppingCart cart2 = (ShoppingCart)context.getBean("shoppingCart");
cart2.addItem(dvdrw);
System.out.println("Shopping Cart2 contains:" + cart2.getItem());
}
}
運行結果爲:
Shopping Cart1 contains:[AAA 2.5, CD-RW 1.5]
Shopping Cart2 contains:[AAA 2.5, CD-RW 1.5, DVD-RW 3.0]
顯然這不是我們想要的結果;我們所要的是每個顧客各獲得一個Bean實例,這時就應該將配置文件中的Bean實例的作用域改爲prototype;
<bean id="shoppingCart" class="com.song.spring.scope.ShoppingCart" scope="prototype"/>
再運行所得結果爲:
Shopping Cart1 contains:[AAA 2.5, CD-RW 1.5]
Shopping Cart2 contains:[DVD-RW 3.0]
這纔是我們想要的結果,完畢!