当通过Spring容器创建一个Bean实例时,不仅可以完成Bean实例的实例化,还可以为Bean指定特定的作用域。Spring支持如下5种作用域:
·singleton:单例模式,在整个Spring IoC容器中,使用singleton定义的Bean将只有一个实例
·prototype:原型模式,每次通过容器的getBean方法获取prototype定义的Bean时,都将产生一个新的Bean实例
·request:对于每次HTTP请求,使用request定义的Bean都将产生一个新实例,即每次HTTP请求将会产生不同的Bean实例。只有在Web应用中使用Spring时,该作用域才有效
·session:对于每次HTTP Session,使用session定义的Bean豆浆产生一个新实例。同样只有在Web应用中使用Spring时,该作用域才有效
·globalsession:每个全局的HTTP Session,使用session定义的Bean都将产生一个新实例。典型情况下,仅在使用portlet context的时候有效。同样只有在Web应用中使用Spring时,该作用域才有效
其中比较常用的是singleton
和prototype
两种作用域。对于singleton
作用域的Bean,每次请求该Bean都将获得相同的实例。容器负责跟踪Bean实例的状态,负责维护Bean实例的生命周期行为;如果一个Bean被设置成prototype作用域,程序每次请求该id的Bean,Spring都会新建一个Bean实例,然后返回给程序。在这种情况下,Spring容器仅仅使用new 关键字创建Bean实例,一旦创建成功,容器不在跟踪实例,也不会维护Bean实例的状态。
还是以demo的形式看看具体有什么差别吧:
创建实例:
package com.jd.scope;
public class AddressDetail {
private String city;
private String street;
private String house;
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getHouse() {
return house;
}
public void setHouse(String house) {
this.house = house;
}
@Override
public String toString() {
return "AddressDetail [city=" + city + ", street=" + street + ", house="
+ house + "]";
}
public AddressDetail() {
System.out.println("AddressDetail constructor is created ....");
}
}
创建配置文件springscope.xml:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="addressDetail" class="com.jd.scope.AddressDetail" >
<property name="city" value="beijing"></property>
<property name="street" value="zhongguancun"></property>
<property name="house" value="3300"></property>
</bean>
</beans>
1.singleton单例
配置作用域为singleton:
<bean id="addressDetail" class="com.jd.scope.AddressDetail" scope="singleton">
测试1:
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("springscope.xml");
}
结果1:
AddressDetail constructor is created ….
测试2:
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("springscope.xml");
AddressDetail addressDetail1 = (AddressDetail)ctx.getBean("addressDetail");
AddressDetail addressDetail2 = (AddressDetail)ctx.getBean("addressDetail");
System.out.println(addressDetail1.getClass()+"---"+addressDetail1.hashCode());
System.out.println(addressDetail2.getClass()+"---"+addressDetail2.hashCode());
System.out.println(addressDetail1==addressDetail2);
}
结果2:
AddressDetail constructor is created ….
class com.jd.scope.AddressDetail—1791868405
class com.jd.scope.AddressDetail—1791868405
true
测试结果显示使用singleton模式,在初始化IoC容器的时候就将实例初始化,在整个Spring IoC容器中,使用singleton定义的Bean将只有一个实例。
2.prototype原型
配置作用域为prototype:
<bean id="addressDetail" class="com.jd.scope.AddressDetail" scope="prototype">
测试1:
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("springscope.xml");
}
结果1:
测试2:
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("springscope.xml");
AddressDetail addressDetail1 = (AddressDetail)ctx.getBean("addressDetail");
AddressDetail addressDetail2 = (AddressDetail)ctx.getBean("addressDetail");
System.out.println(addressDetail1.getClass()+"---"+addressDetail1.hashCode());
System.out.println(addressDetail2.getClass()+"---"+addressDetail2.hashCode());
System.out.println(addressDetail1==addressDetail2);
}
结果2:
AddressDetail constructor is created ….
AddressDetail constructor is created ….
class com.jd.scope.AddressDetail—377478451
class com.jd.scope.AddressDetail—513169028
false
prototype原型模式,在IOC容器初始化的时候并不会实例化,而是在调用的时候才会去创建实例,并且每次getBean都会重新创建一个。
说明:
singleton:默认值,容器初始化时创建bean的实例,在整个容器的生命周期内只创建这一个bean,单例的;
prototype:容器初始化时不创建bean的实例,而在每次请求时都创建一个新的bean实例,并返回;
在struts2中的action中需要将配置成为prototype
每次请求都会传参数过来,如果这个Action是个单例的话,后面请求的参数,就把前面的给覆盖了,所以必须设置成prototype
另外三种暂未研究,作为待续