作用域通俗一点------>表示:有效范围。
Spring Bean的有效范围,在XML中用scope
定义
<bean id="BeanScopeTest" class="com.zing.test.bean.BeanScopeTest" scope="singleton"/>
SpringMVC 中定义了singleton
,prototype
基本作用域和三个web作用域
先解释基本作用域,并且允许用户自己定义作用域
基本作用域
-
singleton
作用域的Bean只会在每个Spring IoC容器中存在一个实例,而且其完整生命周期完全由Spring容器管理。对于所有获取该Bean的操作Spring容器将只返回同一个Bean。
单例模式:就是私有化构造函数,通过唯一的方法获取对象,并且每次获取为同一对象
public class Singleton {
/*1.私有化构造函数*/
private Singleton() {}
//2.单例缓存者,惰性初始化,第一次使用时初始化
private static class InstanceHolder {
private static final Singleton INSTANCE = new Singleton();
}
//3.提供全局访问点
public static Singleton getInstance() {
return InstanceHolder.INSTANCE;
}
}
以上就实现了一个单例模型
Spring把模型通过注册表的方式,将Bean缓存起来,先将Bean通过唯一键注册到表中,再通过键来获取他们,Spring的单例模式是通过注册表实现的,而非代码式单例模式,所以是非侵入式的。
在Spring中,Bean在没有指定作用域的时候,默认是单例模式的。
-
prototype
原型模式,每次都是获取新的对象,跟单例模式不一样,Spring不对prototype模式的Bean进行缓存
Web应用中的作用域
Spring提供了3种在Web中的作用域,分别在request
、session
、globalSession
。这些作用域的有效范围分别如下
-
request
每一次HTTP请求都会产生一个新的bean,这个bean仅在当前request内有效 -
session
每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前session内有效 -
global session
全局session有效,这个是针对portlet的web应用的,具体可以看看Portlet是如何定义了全局Session的。这个有效范围是全局portlet Session的生命周期范围内,如果不是portlet的web应用,那么这个等同于session
作用域。
利用注解定义作用域
很简单,例子如下
@Scope("prototype")
@Component("bean")
public class BeanAnnotation {
public void say(String arg) {
System.out.println(arg);
}
}
自定义bean装配作用域
在2.0之后,Spring支持自己定义作用域了(不能覆盖singleton和prototype这两个现有的作用域)只要实现Scope接口就可以。
我们建立一个线程的scope,该scope在表示一个线程中有效,代码如下:
import org.springframework.beans.factory.config.Scope;
public class MyScope implements Scope {
private final ThreadLocal threadScope = new ThreadLocal() {
protected Object initialValue() {
return new HashMap();
}
};
public Object get(String name, ObjectFactory objectFactory) {
Map scope = (Map) threadScope.get();
Object object = scope.get(name);
if(object==null) {
object = objectFactory.getObject();
scope.put(name, object);
}
return object;
}
public Object remove(String name) {
Map scope = (Map) threadScope.get();
return scope.remove(name);
}
publicvoid registerDestructionCallback(String name, Runnable callback) {
}
public String getConversationId() {
// TODO Auto-generated method stub
return null;
}
}
网友评论