一、Bean的作用域概览

离上篇文章发布有快2个月了,这两个月忙着开发Android游戏相关的东西,所以这个系列还有Go语言的 系列的文章都落下了。今天抽空来写一篇,开始了~ 在Spring中Bean是有作用域(scopes)的,当我们在Spring中定义一个Bean的时候就可以为这个Bean指定 作用域。例如,如果当需要获取Bean时候,想要每次都让Spring产生一个Bean实例,你可以将bean的属性(attribute)设置为 prototype。同样,如果你想要Spring每次都返回同一个bean实例,你可以将bean的属性(attribute) 设置为singleton。Spring框架提供了5种作用域:

###Bean的几种作用域

  • singleton : 如果bean指定了这种作用域,那么在每个Spring IoC容器中只存在单个实例。
  • prototype : 这种作用域下单个bean可以拥有多个实例。
  • request : 该作用域将bean定义在了一次HTTP请求中。因此在一次HTTP请求中,容器会返回该bean的同一个实例, 而对于不同的请求,会返回不同的实例。注意:该作用域仅在基于Web的Spring ApplicationContext情形下有效, 比如XmlWebApplicationContext。如果使用ClassPathXmlApplicationContext,会报IllegalStateException的错误。下面的 session和global-seesion也是这样。
  • session : 该作用域将bean定义在了Session中。
  • global-session : 和request,session类似,不同的是请求的作用域变成了全局的HTTP Session中。 典型的应用场景是在使用portlet context的时候有效。

本篇主要介绍singleton和prototype两个作用域,后面三个将在讲基于web的Spring ApplicationContext 时再介绍。

二、singleton作用域

在未指定的作用域情况下该作用域为默认作用域。如果作用域被设置为singleton,那么不管你调用多少次, Spring IoC 容器只会产生一个由bean定义的对象实例,可以理解为该对象实例被缓存了,后面不管多少次请求 都将获取被缓存起来的同一个对象实例。 下面看一个简单的例子:

public class User {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
}

public class MainTest {
public static void main(String[] args) {
    ApplicationContext context = new ClassPathXmlApplicationContext("UserBeans.xml");
    User userA = (User) context.getBean("User");
    userA.setName("Sam");
    System.out.println(userA.getName());
    User userB = (User) context.getBean("User");
    System.out.println(userB.getName());


}

<?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-3.2.xsd">

  <!-- scope="singleton" 也可以省略-->
 <bean id="User" class="sk.spring.tuto.demo3.User" scope="singleton"></bean>
</beans>

运行上述,结果发现打印的都是sam,说明引用的是同一个对象

三、prototype作用域

如果作用域被指定为prototype,那么每次请求指定的bean时(注入到另外一个bean中或者调用getBean()方法时), 都会创建一个新的对象实例。也来看下示例,其它不变就修改下UserBeans.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-3.2.xsd">

    <bean id="User" class="sk.spring.tuto.demo3.User" scope="prototype"></bean>
</beans>

结果打印sam和null,说明引用的不是同一个对象实例。

五、总结

本篇简单介绍了下Spring bean的作用域,主要详细介绍了singleton和prototype两种。

参考:http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/overview.html

##文档信息