Spring入门学习——设置Bean作用域

来源:互联网 发布:我的世界透视矿物js 编辑:程序博客网 时间:2024/06/06 16:44
当在配置文件中声明Bean时,实际上只是定义了Bean创建的一个模板,而不是实际的Bean实例。当getBean()方法或者其他Bean的一个引用请求这个Bean时,Spring将根据Bean作用域(Scope)确定应该返回的Bean实例。因此,有时候应为Bean设置正确的作用域而不是使用默认的作用域。
默认情况下,Spring为IoC容器中声明的每个Bean创建一个实例,这个实例将在整个IoC容器的范围内共享。所有后续的getBean()调用和Bean引用都将返回这个独特的Bean实例,这种作用域称为singleton,是所有Bean的默认作用域。

Spring中的有效Bean作用域
 作用域 描述 Singleton 每个Spring IoC容器中创建一个Bean实例 Prototype 每次请求时创建一个新的Bean实例 Request 为每个HTTP请求创建一个Bean实例,仅在Web应用上下文中有效 Session 为每个HTTP会话创建一个Bean实例,仅在Web应用上下文中有效 GlobalSession 为每个全局HTTP会话创建一个Bean实例,仅在门户应用上下文中有效
应用场景:使用一个购物车示例来学习这个Bean作用域。 需要使用到之前的商品折扣代码:here

package com.cgy.springrecipes.shop;

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> getItems() {
return items;
}
}

配置文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">

<bean id="battery" class="com.cgy.springrecipes.shop.Battery">
<property name="name" value="AAA"/>
<property name="price" value="2.5"/>
</bean>

<bean id="disc1" class="com.cgy.springrecipes.shop.Disc">
<property name="name" value="taylor"/>
<property name="price" value="1.5"/>
</bean>

<bean id="disc2" class="com.cgy.springrecipes.shop.Disc">
<property name="name" value="jackson"/>
<property name="price" value="3.0"/>
</bean>

<bean id="shoppingCart" class="com.cgy.springrecipes.shop.ShoppingCart"/>

</beans>

配置文件内容没什么特别,只是配置了三个商品Bean,一个购物车Bean。

现在编写Main来进行测试,代码如下:

package com.cgy.springrecipes.shop;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans_two.xml");
Product battery = (Product) context.getBean("battery");
Product disc1 = (Product) context.getBean("disc1");
Product disc2 = (Product) context.getBean("disc2");
ShoppingCart cart1 = (ShoppingCart) context.getBean("shoppingCart");
//购物车1添加两样商品
cart1.addItem(battery);
cart1.addItem(disc1);
//查看购物车1内的商品
System.out.println("Shopping cart 1 contains "+cart1.getItems());
//创建一个新的购物车
ShoppingCart cart2 = (ShoppingCart) context.getBean("shoppingCart");
//购物车2添加一样尚品
cart2.addItem(disc2);
//查看购物车2内的商品
System.out.println("Shopping cart 2 contains "+cart2.getItems() );

}
}

控制台输出结果如下:

Shopping cart 1 contains [AAA 2.5, taylor 1.5]
Shopping cart 2 contains [AAA 2.5, taylor 1.5, jackson 3.0]

如果在一开始没有学习Bean的作用域时,相信可能会感到这个结果有点奇怪,为什么不是

Shopping cart 1 contains [AAA 2.5, taylor 1.5]
Shopping cart 2 contains [jackson 3.0]

???
学习了作用域后这个问题就很容易理解,因为Spring IoC里面Bean的作用域默认为singleton,意味着Spring为每个IoC容器创建一个购物车实例,因此尽管代码看上去创建了两个购物车,实际上还是只有一个,因此输出结果自然没问题。

在商品应用中,当然期望每个顾客调用getBean()方法时获得不同的购物车实例,因此为了达到这种表现,应该讲shoppingCart的Bean作用域改为prototype。代码如下:

<bean id="shoppingCart" class="com.cgy.springrecipes.shop.ShoppingCart" scope="prototype"/>


0 0