在介绍IoC容器最顶级接口BeanFactory的时候,可以看到isSingleton和isPrototype两个方法。
其中,isSingleton方法如果返回true,则Bean在IoC容器中以单例存在,也就是Spring IoC容器的默认值如果isPrototype方法返回true,则我们每次获取Bean的时候,IoC容器就会创建一个新的Bean,这显然存在很大不同,这就是Spring Bean的作用域问题。
在一般容器中。Bean都会存在单例(singleton)和原型(prototype)两种作用域,Java EE广泛的使用在互联网中,而在web容器中,则存在页面(page),请求(request),会话(session),应用(application)4种作用域。对于页面(page),是针对JSP的当前页面的作用域,所以Spring无法提供支持。
为了满足各种作用域,在Spring的作用域中存在一下几种类型。
下面探讨单例和原型的区别,首先定义一个类,如代码清单所示
/**
* 定义作用域类
*/
@Component
//@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class ScopeBean {
}
这样就是启动默认的类,实际上就是单例。为了证明作用域的存在,做一下测试
public class IoCTest {
private static Logger log = Logger.getLogger(String.valueOf(IoCTest.class));
public static void main(String[] args){
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
// DataBaseProperties dataBaseProperties = ctx.getBean(DataBaseProperties.class);
ScopeBean scopeBean1 = ctx.getBean(ScopeBean.class);
ScopeBean scopeBean2 = ctx.getBean(ScopeBean.class);
System.out.println(scopeBean1==scopeBean2);
}
}
测试结果:
从测试结果看都指向了同一个实例,所以在IoC容器中只有一个ScopeBean的实例。然后取消注释测试结果如下
很明显不一样了,因为作用域修改为prototype,这样每次获取Bean都是新建一个实例。
下面给出在Spring MVC作用范围内的请求作用域
/**
* 定义作用域类
*/
@Component
//@Scope(WebApplicationContext.SCOPE_REQUEST)
public class ScopeBean {
}
这样同一个请求范围去获取这个Bean的时候,只会共用同一个Bean但是,第二次请求就会产生新的Bean。因此两个不同的请求将获得不同的实例,这点要注意。!!