Spring2.5学习1.4_bean的作用域及其实例化时期

由于目前的工程是纯java工程,只对前两种域进行代码演示,后面三中会在以后的web项目中进行详解。

Spring Framework支持五种作用域(其中有三种只能用在基于webSpring ApplicationContext)。

1、singleton:当一个bean的作用域为singleton, 那么Spring IoC容器中只会存在一个共享的bean实例,并且所有对bean的请求,只要id与该bean定义相匹配,则只会返回bean的同一实例。bean是在Spring容器初始化的过程中生成的,ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");

注意Singleton作用域是Spring中的缺省作用域。要在XML中将bean定义成singleton,可以这样配置: 

<bean id="empServiceImpl" class="cn.csdn.service.EmpServiceImpl" scope="singleton">

2、prototype一个bean定义对应多个对象实例Prototype作用域的bean会导致在每次对该bean请求(将其注入到另一个bean中,或者以程序的方式调用容器的getBean()方法)时都会创建一个新的bean实例。根据经验,对有状态的bean应该使用prototype作用域,而对无状态的bean则应该使用singleton作用域。bean是在调用getBean("personService");方法时生成的,这个也不难理解,如果不调用getBean()方法,容器怎么知道应该对那个bean进行实例化呢?


以下是相关代码片段及其运行结果

1.bean的作用域在默认状态下是singleton类型

bean配置(缺省,或者scope="singleton"):

<bean id="personService" class="xjj.service.impl.PersonServiceBean"></bean>
SpringTest2

package junit.test;

import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import xjj.service.PersonService;
public class SpringTest2 {

	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
	}

	@Test public void instanceSpring(){
		
		ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
		PersonService personService = (PersonService)ctx.getBean("personService");
		PersonService personService2 = (PersonService)ctx.getBean("personService");
		System.out.println(personService==personService2);
		
	}
}
结果:返回结果是true,证明两次获取的bean是同一个实例。

2.bean的作用域是prototype

bean配置:

 <bean id="personService" class="xjj.service.impl.PersonServiceBean" scope="prototype"></bean>
SptingTest2文件类容同上

结果:返回结果的false,说明两次获取的是不同的bean实例。
3.bean的实例化时期

PersonServiceBean.java类

package xjj.service.impl;

import xjj.service.PersonService;

public class PersonServiceBean implements PersonService {
	 public void init(){
	 System.out.println("初始化");
	 }
	public PersonServiceBean() {
		System.out.println("我被实例化了");
	}

	public void save() {
		System.out.println("我是save()方法");
	}

	public void destory() {
		System.out.println("开闭打开的资源");
	}
}
bean配置中可以通过更改scope属性,设置不同域
SpringTest2可以通过注掉第二行代码,根据是否执行构造方法PersonServiceBean()来判断实例化时期

ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
PersonService personService1 = (PersonService)ctx.getBean("personService");
结果:scope="prototype",在注释掉第二行代码是,没有输出,然后再恢复第二行代码


4.当作用域是singleton时,可以在bean中添加lazy-init="true"属性,对bean的实例化时期进行延时,使其在调用getBean()方法时实例化,

如果想让所有singleton域的bean都延时初始化,可以在其父节点beans添加属性default-lazy-init="true"

5.在实例化bean之后立即进行某些操作(比如链接数据库),可以在bean中添加init-method="方法名",例如想执行PersonServiceBean中的init方法

bean配置:

<bean id="personService" class="xjj.service.impl.PersonServiceBean" init-method="init"</bean>
结果:先实例化bean,再执行初始化方法

6.bean使用完以后,正常销毁bean,添加属性: destroy-method="destory" 

bean配置:

<bean id="personService" class="xjj.service.impl.PersonServiceBean" init-method="init"destroy-method="destory"</bean>
SpringTest2,通过引用抽象类AbstractApplicationContext,调用close方法,关闭资源

AbstractApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
ctx.close();
结果:
另外三种作用域介绍:

3、request在一次HTTP请求中,一个bean定义对应一个实例;即每次HTTP请求将会有各自的bean实例, 它们依据某个bean定义创建而成。该作用域仅在基于webSpring ApplicationContext情形下有效。

考虑下面bean定义:

<bean id="loginAction" class=cn.csdn.LoginAction" scope="request"/>

针对每次HTTP请求,Spring容器会根据loginAction bean定义创建一个全新的LoginAction bean实例, 且该loginAction bean实例仅在当前HTTP request内有效,因此可以根据需要放心的更改所建实例的内部状态, 而其他请求中根据loginAction bean定义创建的实例,将不会看到这些特定于某个请求的状态变化。 当处理请求结束,request作用域的bean实例将被销毁。

4、session在一个HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于webSpring ApplicationContext情形下有效。

考虑下面bean定义:

<bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/>

针对某个HTTP SessionSpring容器会根据userPreferences bean定义创建一个全新的userPreferences bean实例, 且该userPreferences bean仅在当前HTTP Session内有效。 与request作用域一样,你可以根据需要放心的更改所创建实例的内部状态,而别的HTTP Session中根据userPreferences创建的实例, 将不会看到这些特定于某个HTTP Session的状态变化。 当HTTP Session最终被废弃的时候,在该HTTP Session作用域内的bean也会被废弃掉。

5、global session在一个全局的HTTP Session中,一个bean定义对应一个实例。典型情况下,仅在使用portlet context的时候有效。该作用域仅在基于webSpring ApplicationContext情形下有效。

考虑下面bean定义:

<bean id="userPreferences" class="com.foo.UserPreferences" scope="globalSession"/>

global session作用域类似于标准的HTTP Session作用域,不过它仅仅在基于portletweb应用中才有意义。Portlet规范定义了全局Session的概念,它被所有构成某个portlet web应用的各种不同的portlet所共享。在global session作用域中定义的bean被限定于全局portlet Session的生命周期范围内。

请注意假如你在编写一个标准的基于Servletweb应用,并且定义了一个或多个具有global session作用域的bean,系统会使用标准的HTTP Session作用域,并且不会引起任何错误。


posted @ 2015-05-31 18:01  小鲜肉成长记  阅读(154)  评论(0编辑  收藏  举报