scope用来声明容器中的对象所应该处的限定场景或者说该对象的存活时间,即容器在对象进入其相应的scope之前,生成并装配这些对象,在该对象不再处于这些scope的限定之后,容器通常会销毁这些对象。
Spring容器最初提供了两种bean的scope类型:singleton和prototype,但发布2.0之后,又引入了另外三种scope类型,即request,session和global session类型。不过这三种类型有所限制,自能在Web应用中使用。也就是说,只有在支持Web应用的ApplicationContext中使用这三个scope才是合理的。
我们可以通过使用<bean>的singleton或者scope属性来指定相应对象的scope,其中,scope属性只能在xsd格式的文档声明中使用,类似于如下代码所演示的形式:
DTD:
<bean id="mockObject1" class="...MockBusinessObject" singleton="false"/>
XSD:
<bean id="mockObject1" class="...MockBusinessObject" scope="prototype"/>
让我们来看一下容器提供的这几个scope是如何限定相应对象的吧!
1.singleton
标记为拥有singleton scope的对象定义,在Spring的IoC容器中只存在一个实例,所有对该对象的引用将共享这个实例。该实例从容器启动,并因为第一次请求而初始化之后,将一直存活到容器退出,也就是说,它与IoC容器“几乎”拥有相同的“寿命”。通常情况下,如果你不指定bean的scope,singleton便是容器默认的scope。所以,下面三种配置形式实际上达成的是同样的效果。
<!-- DTD or XSD --> <bean id="mockObject1" class="...MockBusinessObject"/> <!-- DTD --> <bean id="mockObject1" class="...MockBusinessObject" singleton="true"/> <!-- XSD --> <bean id="mockObject1" class="...MockBusinessObject" scope="singleton"/>
2.prototype
针对声明为拥有prototype scope的bean定义,容器在接到该类型对象的请求的时候,会每次都重新生成一个新的对象实例给请求方。虽然这种类型的对象的实例化以及属性设置等工作都是由容器负责的,但是只要准备完毕,并且对象实例返回给请求方之后,容器就不再拥有当前返回对象的引用,请求方需要自己负责当前返回对象的后继生命周期的管理工作,包括对象的销毁。
你用以下形式来指定某个bean定义的scope为prototype类型,效果是一样的:
<!-- DTD --> <bean id="mockObject1" class="...MockBusinessObject" singleton="false"/> <!-- XSD --> <bean id="mockObject1" class="...MockBusinessObject" scope="prototype"/>
3.request、session和global session
这三个scope类型是Spring 2.0之后新增加的,它们不像之前的singleton和prototype那么“通用”。因为它们只适用于Web应用程序,通常与XmlWebApplicationContext共同使用。注意,只能使用scope属性才能指定这三种“bean的scope类型”。也就是说,你不得不使用基于XSD文档声明的XML配置文件格式。
• request
request通常的配置形式如下:
<bean id="requestProcessor" class="...RequestProcessor" scope="request"/>
Spring容器,即XmlWebApplicationContext会为每个HTTP请求创建一个全新的RequestProcessor对象供当前请求使用,当请求结束后,该对象实例的生命周期即告结束。当同时有十个HTTP请求进来的时候,容器会分别针对这十个请求返回十个全新的RequestProcessor对象实例,且它们之间互不干扰。从不是很严格的意义上说,request可以看作prototype的一种特例,除了场景更加具体之外,语义上差不多。
• session
对于Web应用来说,放在session中的最普遍的信息就是用户的登录信息,对于这种放在session中的信息,我们可使用如下形式指定其scope为session:
<bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/>
Spring容器会为每个独立的session创建属于它们自己的全新的UserPreferences对象实例。与request相比,除了拥有session scope的bean的实例具有比request scope的bean可能更长的存活时间,其他方面真是没什么差别。
• global session
还是userPreferences,不过scope对应的值换一下,如下所示:
<bean id="userPreferences" class="com.foo.UserPreferences" scope="global session"/>
global session只有应用在基于portlet的Web应用程序中才有意义,它映射到portlet的global范围的session。如果在普通的基于servlet的Web应用中使用了这个类型的scope,容器会将其作为普通的session类型的scope对待。
文章摘抄自《Spring揭秘》。