Spring bean作用域解析

默认情况下,所有的 Spring Bean 都是单例的,也就是说在整个 Spring 应用中, Bean 的实例只有一个。

我们可以在 <bean> 元素中添加 scope 属性来配置 Spring Bean 的作用范围。例如,如果每次获取 Bean 时,都需要一个新的 Bean 实例,那么应该将 Bean 的 scope 属性定义为 prototype,如果 Spring 需要每次都返回一个相同的 Bean 实例,则应将 Bean 的 scope 属性定义为 singleton。

spring bean作用域定义:
spring bean 作用域

singleton

singleton 是 Spring 容器默认的作用域。当 Bean 的作用域为 singleton 时,Spring IoC 容器中只会存在一个共享的 Bean 实例。这个 Bean 实例将存储在高速缓存中,所有对于这个 Bean 的请求和引用,只要 id 与这个 Bean 定义相匹配,都会返回这个缓存中的对象实例。

如果一个 Bean 定义的作用域为 singleton ,那么这个 Bean 就被称为 singleton bean。在 Spring IoC 容器中,singleton bean 是 Bean 的默认创建方式,可以更好地重用对象,节省重复创建对象的开销。

在 Spring 配置文件中,可以使用 <bean> 元素的 scope 属性,将 Bean 的作用域定义成 singleton,其配置方式如下所示:

<bean id="..." class="..." scope="singleton"/>

prototype

如果一个 Bean 定义的作用域为 prototype,那么这个 Bean 就被称为 prototype bean。对于 prototype bean 来说,Spring 容器会在每次请求该 Bean 时,都创建一个新的 Bean 实例。

从某种意义上说,Spring IoC 容器对于 prototype bean 的作用就相当于 Java 的 new 操作符。它只负责 Bean 的创建,至于后续的生命周期管理则都是由客户端代码完成的。

在 Spring 配置文件中,可以使用 <bean> 元素的 scope 属性将 Bean 的作用域定义成 prototype,其配置方式如下所示:

<bean id="..." class="..." scope="prototype"/>

实例:

下面我们就通过一个简单的实例,对 Bean 的 prototype 作用域进行演示。

  1. 在 net.test 包中,创建一个名为 PrototypeBean 的类,代码如下。
package net.test;

public class PrototypeBean {
    private String str;
    public void setStr(String str) {
        this.str = str;
    }
}
  1. 在 Beans.xml 中,添加 PrototypeBean 的 Bean 的定义,配置如下。
<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.0.xsd">
    <!--单例模式 singleton-->
    <bean id="singletonBean" class="net.test.SingletonBean" scope="singleton">
        <property name="str" value="IT懒猫"></property>
    </bean>
    <!--原型模式 prototype-->
    <bean id="prototypeBean" class="net.test.PrototypeBean" scope="prototype">
        <property name="str" value="www.catroom.com.cn"></property>
    </bean>
</beans>
  1. 对 MainApp 中的代码进行修改。
package net.test;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainApp {
    private static final Log LOGGER = LogFactory.getLog(MainApp.class);
    public static void main(String[] args) {
        //获取 ApplicationContext 容器
        ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
        PrototypeBean prototypeBean = context.getBean("prototypeBean", PrototypeBean.class);
        PrototypeBean prototypeBean2 = context.getBean("prototypeBean", PrototypeBean.class);
        System.out.println(prototypeBean);
        System.out.println(prototypeBean2);
    }
}
  1. 执行 MainApp 中的 main 函数,控制台输出如下。
net.test.PrototypeBean@61f8bee4
net.test.PrototypeBean@7b49cea0

从运行结果可以看出,两次输出的内容并不相同,这说明在 prototype 作用域下,Spring 容器创建了两个不同的 prototypeBean 实例。