在配置文件中定义Bean时,用户不但可以配置Bean的属性值以及相互之间的依赖关系,还可以定义Bean的作用域。
作用域将对Bean的生命周期和创建方式产生影响,在低版本的Spring中,仅有两个作用域:singleton 和 prototype。
在Sprign2.0中,针对WebApplicationContext新添加了3个新的作用域:request,session,globalSession。
一、singleton和prototype
在低版本的Spring中,由于仅有两个作用域:singleton 和 prototype,所以采用singleton="true|false"的配置方式,Spring为了向后兼容,依旧支持这种配置方式,不过Spring推荐采用新的配置方式:scope="作用域类型"。
1.singleton作用域
Spring以容器的方式提供天然的单实例模式功能,任何POJO无需编写特殊的 代码仅通过配置就可以想用单实例模式的大餐。
因为Spring利用AOP和LocalThread的功能,对非线程安全的变量进行了特殊的处理,使这些非线程安全的类变成了线程安全的类。
public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); //singleton的bean Car car1 = ctx.getBean("car1",Car.class); System.out.println("单例的car1:"+car1); car1.setBrand("改变"); Car car2 = ctx.getBean("car1",Car.class); System.out.println("再次获取单例的car1:"+car2); }
输出:
单例的car1:the car is:spring注入-红旗001, color is:spring注入-紫色, maxspeed is:520
再次获取单例的car1:the car is:改变, color is:spring注入-紫色, maxspeed is:520在默认的情况下,Spring的ApplicationContext容器在启动的时候,自动实例化所有的singleton的Bean并缓冲与容器中。
a.这样首先对Bean提前的实例化操作会及早发现一些潜在的配置问题
b.Bean将以缓存方式保存,当再次使用时无需再实例化了
如果用户不希望在容器启动时实例化singleton的Bean,可以通过lazy-init属性进行控制:
lazy-init="true"的Bean在某些特殊情况下依旧会提前实例化:如果该Bean被其他需要提前实例化的Bean引用到。
2.prototype作用域
在默认情况下,Spring容器在启动时不实例化prototype的Bean,此外,Spring容器讲prototype的Bean交给调用者后,就不再管理它的生命周期。
public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); //prototype的bean Car carPrototype1 = ctx.getBean("carPrototype",Car.class); System.out.println("多例的carPrototype:"+carPrototype1); carPrototype1.setBrand("改变"); Car carPrototype2 = ctx.getBean("carPrototype",Car.class); System.out.println("再次获取多例的carPrototype:"+carPrototype2);}
输出:
多例的carPrototype:the car is:邦德, color is:黑色, maxspeed is:110
再次获取多例的carPrototype:the car is:邦德, color is:黑色, maxspeed is:110每次getBean都将得到一个最新状态的Bean.
二、Web应用环境相关的Bean的作用域
1.request作用域
request作用域的Bean对应一个HTTP请求和生命周期,每次HTTP请求到carBean时,Spring容器创建一个新的carBean,请求处理完毕,销毁这个Bean.
2.session作用域
carBean的作用域将横跨整个HTTP Session,Session中所有的HTTP请求都将共享一个carBean,当HTTP Session结束后,实例才被销毁。
3.globalSession作用域
在
globalSession作用域类似于session作用域,不过仅在Portlet的web应用中使用。Portlet规范定义了全局Sesson的概念,它被组成portletweb应用的所有子portlet共享。如果不在Portlet的web应用中使用,globalSession自然就等价于session作用域了。