SpringBean的作用域

Spring Framework支持五种作用域(其中有三种只能用在基于Web的Spring ApplicationContext)。

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 情形下有效。

Singleton作用域

当一个bean的作用域为singleton, 那么Spring IoC容器中只会存在一个共享的bean实例,并且所有对bean的请求,只要id与该bean定义相匹配,则只会返回bean的同一实例。换言之,当把一个bean定义设置为singlton作用域时,Spring IoC容器只会创建该bean定义的唯一实例。这个单一实例会被存储到单例缓存(singleton cache)中,并且所有针对该bean的后续请求和引用都将返回被缓存的对象实例。

请注意Spring的Singleton Bean概念与GoF模式一书中定义的Singleton模式是完全不同的。经典的GoF Singleton模式中所谓的对象范围是指在每一个ClassLoader 中 指定class创建的实例有且仅有一个 。把Spring的singleton作用域描述成一个Container (容器)对应一个bean 实例最为贴切。也就是说假如在单个Spring容器内定义了某个指定Class的Bean,那么Spring容器将会创建一个并且仅有一个 由该Bean定义指定的类实例。Singleton作用域是Spring中的缺省作用域 。要在XML中将Bean定义成Singleton。

可以这样配置:

<bean id="accountService" class="com.vernon.DefaultAccountService"/>  

<bean id="accountService" class="com.vernon.DefaultAccountService" scope="singleton"/>  

<bean id="accountService" class="com.vernon.DefaultAccountService" singleton="true"/> 

Prototype作用域

Prototype作用域的bean会导致在每次对该Bean请求(将其注入到另一个Bean中,或者以程序的方式调用容器的getBean() 方法)时都会创建一个新的Bean实例 。根据经验,对有状态的Bean应该使用Prototype作用域,而对无状态的Bean则应该使用Singleton作用域。
下图演示了Spring的Prototype作用域。请注意,通常情况下,DAO不会被配置成Prototype,因为DAO通常不会持有任何会话状态,因此应该使用Singleton作用域。

在XML中将bean定义成prototype,可以这样配置:

<bean id="accountService" class="com.vernon.DefaultAccountService" scope="prototype"/>  

<bean id="accountService" class="com.vernon.DefaultAccountService" singleton="false"/>  

其他作用域,即Request、Session以及Global Session 仅在基于web的应用中使用(不必关心你所采用的是什么Web应用框架)。这些作用域仅仅在使用基于Web的Spring ApplicationContext实现(如XmlWebApplicationContext)时有用。 如果在普通的Spring IoC容器中,比如像XmlBeanFactory或ClassPathXmlApplicationContext, 尝试使用这些作用域,你将会得到一个IllegalStateException异常(未知的bean作用域)。