Spring Bean的作用域
我们知道Spring中的对象是通过Bean的的方式来进行管理的,Bean的作用域默认是单利的(singleton)
xml 中的配置如下:
<bean id="bean" class="cn.zhuoqianmingyue.ioc.scope.Bean" scope="singleton"></bean>
进行测试:
我们获取3次Bean类的实例对象,通过打印对象的哈希值来进行判断。
测试代码如下:
public class ScopeTest {
@Test
public void singleton() {
ApplicationContext appliction = new ClassPathXmlApplicationContext("ioc-scope.xml");
Bean user = (Bean)appliction.getBean("bean");
Bean user2 = (Bean)appliction.getBean("bean");
Bean user3 = (Bean)appliction.getBean("bean");
System.out.println(user.toString());
System.out.println(user2.toString());
System.out.println(user3.toString());
}
}
测试结果:
通过上面代码测试我们证实了Spring 配置 scope=“singleton” 创建实例对象默认是单例的。
在每个Spring IoC容器中,一个bean定义对应只会有唯一的一个bean实例。
在实际开发中可能我们需要实例对象不想设置成单利的 ,Spring的作用域 还为我们提供了 另外六种分别为:
1. prototype
一个bean定义可以有多个bean实例。原型模式 每次创建的都是新的实例对象。
2. request
一个bean定义对应于单个HTTP 请求的生命周期。也就是说,每个HTTP 请求都有一个bean实例,且该实例仅在这个HTTP 请求的生命周期里有效。该作用域仅适用于WebApplicationContext环境。相当于调用 request.setAttribute(“bean”,Bean);
3. session
一个bean 定义对应于单个HTTP Session 的生命周期,也就是说,每个HTTP Session 都有一个bean实例,且该实例仅在这个HTTP Session 的生命周期里有效。该作用域仅适用于WebApplicationContext环境。相当于 调用 request.getSession().setAttribute(“bean”,Bean);
4. application
一个bean 定义对应于单个ServletContext 的生命周期。该作用域仅适用于WebApplicationContext环境。相当于调用
servletContext.setAttribute(“bean”,Bean);
5. websocket
一个bean 定义对应于单个websocket 的生命周期。该作用域仅适用于WebApplicationContext环境。这个没有自己没有实际应用过。不太了解
6. globalSession
一个bean 定义范围限定为全局HTTP的生命周期Session,只适用于基于portlet的web应用程序的上下文。这个没有自己没有实际应用过。不太了解
Spring Bean的生命周期
我们拿人来举例,生命周期就是 一个婴儿从诞生到变老死亡的的过程。在Spring中由于Bean的实例化都是Spring框架来完成的,这个过程我们是无法进行干预的。但是Spring为我们提供了2个回调方法 init-method 和destory-method。
接下来我们进行回调方法配置来观察Spring的声明周期执行过程:
首先创建名称为Bean类,创建init 和destroy方法代码如下:
package cn.zhuoqianmingyue.ioc.scope;
public class Bean {
public void init() {
System.out.println("init......");
}
public void destroy() {
System.out.println("destroy......");
}
}
将Bean类配置到Spring配置文件中,并通过init-method 和destroy-method指定初始化和销毁调用的方法。
<bean id="bean" class="cn.zhuoqianmingyue.ioc.scope.Bean" init-method="init" destroy-method="destroy"></bean>
进行测试:
首先我们测试初始化的操作,通过实例化Spring容器看看 init方法是否被调用。
测试代码如下:
public class LifecycleTest {
@Test
public void beanLifecycleInit() {
ApplicationContext application = new ClassPathXmlApplicationContext("ioc-lifecycle.xml");
}
}
测试结果:
由于ApplicationContext 没有提供容器关闭的操作,我们通过ClassPathXmlApplicationContext 来完成我们的容器关闭操作
测试代码如下:
@Test
public void beanLifecycleInitAndDestroy() {
ClassPathXmlApplicationContext application = new ClassPathXmlApplicationContext("ioc-lifecycle.xml");
Bean bean = (Bean)application.getBean("bean");
application.close();
}
测试结果:
Spring的Bean是在我们的容器初始化时进行创建,当我们的容器关闭或者销毁时Bean会进行销毁。
需要注意的是Bean的销毁只能操作作用域是单利的Bean,对于非单利的Bean Spring只是负责创建,而销毁的操作和我们普通new 出来的实例对象一样通过JVM垃圾回收进行进行销毁的。