Spring注解之@Scope

时间:2024-05-30 16:15:17

Spring注解之@Scope



基于spring4.0版本

scope官方定义:
When you create a bean definition, you create a recipe for creating actual instances of the class defined by that bean definition. The idea that a bean definition is a recipe is important, because it means that, as with a class, you can create many object instances from a single recipe.

分类:
1、singleton:    
    (Default) Scopes a single bean definition to a single object instance per Spring IoC container.

2、prototype:    
    Scopes a single bean definition to any number of object instances.


3、request:
    Scopes a single bean definition to the lifecycle of a single HTTP request; that is, each HTTP request has its own instance of a bean created off the back of a single bean definition. Only valid in the context of a web-aware Spring ApplicationContext.


4、session:
    Scopes a single bean definition to the lifecycle of an HTTP Session. Only valid in the context of a web-aware Spring ApplicationContext.


5、globalSession:
    Scopes a single bean definition to the lifecycle of a global HTTP Session. Typically only valid when used in a Portlet context. Only valid in the context of a web-aware Spring ApplicationContext.


6、application:
    Scopes a single bean definition to the lifecycle of a ServletContext. Only valid in the context of a web-aware Spring ApplicationContext.


7、websocket:
    Scopes a single bean definition to the lifecycle of a ServletContext. Only valid in the context of a web-aware Spring ApplicationContext.

以下两种singleton和prototype最常用,故先做区分:
1、spring 默认scope 是单例模式。
2、@Scope("prototype")放在spring项目的controller层,防止请求重复提交。
3、Spring在Action上面注解@Scope("prototype"):表示每次接收一个请求创建一个Action对象。
如若改成其他@Scope("singleton"),例如单例模式,则很多请求公用同一个Action。
     eg:一个注册的例子,如果没加上这个注解,注册完成后,下一个请求再注册一次,Action里会保留上一次注册的信息。

比喻:
1. singleton(滑梯):
    singleton类型的bean定义,在一个容器中只存在一个实例,所有对该类型bean的依赖都引用这一单一实例,这就好像每个幼儿园都会有一个滑梯一样,这个幼儿园的小朋友共同使用这一个滑梯,而对于幼儿园容器来说,滑梯就是一个singleton的bean。

    此外,singleton类型的bean定义,从容器启动,到他第一次被请求而实例化开始,只要容器不销毁或退出,该类型的bean的单一实例就会一直存活。通常情况下,如果你不指定bean的scope,singleton便是容器默认的scope。

2. prototype(分苹果
    scope为prototype的bean,容器在接受到该类型的对象的请求的时候,会每次都重新 生成一个新的对象给请求方,虽然这种类型的对象的实例化以及属性设置等工作都是由容器负责的,但是只要准备完毕,并且对象实例返回给请求方之后,容器就不 在拥有当前对象的引用,请求方需要自己负责当前对象后继生命周期的管理工作,包括该对象的销毁。也就是说,容器每次返回请求方该对象的一个新的实例之后, 就由这个对象“自生自灭”了。

    让我们继续幼儿园的比喻,我们今天要分苹果了!将苹果的bean的scope属性声明为 prototype,在每个小朋友领取苹果的时候,我们都是发一个新的苹果给他,发完之后,小朋友爱怎么吃就怎么吃,爱什么时候吃什么时候吃,但是注意吃 完要把果核扔到垃圾箱哦!对于那些不能共享使用的对象类型,应该将其定义的scope设为prototype,通常,声明为prototype的 bean,都是一些有状态的,比如保存为每个顾客信息的对象。

 

代码说话:

package com.yiibai.customer.services;

public class CustomerService {
	String message;
	
	public String getMessage() {
		return message;
	}

	public void setMessage(String message) {
		this.message = message;
	}
}

 

1.单例例子
如果 bean 配置文件中没有指定 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-2.5.xsd">

       <bean id="customerService" 
            class="com.yiibai.customer.services.CustomerService" />
		
</beans>

执行结果:

package com.yiibai.common;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.yiibai.customer.services.CustomerService;

public class App {
    public static void main( String[] args )    {
    	ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"Spring-Customer.xml"});

    	CustomerService custA = (CustomerService)context.getBean("customerService");
    	custA.setMessage("Message by custA");
    	System.out.println("Message : " + custA.getMessage());
    	
    	//retrieve it again
    	CustomerService custB = (CustomerService)context.getBean("customerService");
    	System.out.println("Message : " + custB.getMessage());
    }
}

输出结果

Message : Message by custA
Message : Message by custA 

由于 bean 的 “CustomerService' 是单例作用域,第二个通过提取”custB“将显示消息由 ”custA' 设置,即使它是由一个新的 getBean()方法来提取。在单例中,每个Spring IoC容器只有一个实例,无论多少次调用 getBean()方法获取它,它总是返回同一个实例。

 

2.原型例子
如果想有一个新的 “CustomerService”bean 实例,每次调用它的时候,需要使用原型(prototype)来代替。
<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-2.5.xsd">

   <bean id="customerService" class="com.yiibai.customer.services.CustomerService" 
         scope="prototype"/>
		
</beans>

运行-执行

Message : Message by custA
Message : null
在原型作用域,必须为每个 getBean()方法中调用返回一个新的实例。