spring Bean的作用范围和生命周期
本文目录
一.Spring Bean的作用域
Spring bean 的 5 种作用域,详细介绍 singleton
和 prototype
这两种最常用的作用域。
标签的scope
属性用于指定bean的作用范围,常用的就是单例的和多例的;
1.1 作用域的种类
Spring 容器在初始化一个 Bean 的实例时,同时会指定该实例的作用域。Spring3 为 Bean
定义了五种作用域,具体如下。
- 1)singleton
单例模式,使用 singleton 定义的 Bean 在 Spring 容器中只有一个实例,这也是 Bean 默认的作用域。 - 2)prototype
多例(原型)模式,每次通过 Spring 容器获取 prototype 定义的 Bean 时,容器都将创建一个新的 Bean 实例。 - 3)request
在一次 HTTP 请求中,容器会返回该 Bean 的同一个实例。而对不同的 HTTP 请求,会返回不同的实例,该作用域仅在当前 HTTP Request 内有效。 - 4)session
在一次 HTTP Session 中,容器会返回该 Bean 的同一个实例。而对不同的 HTTP 请求,会返回不同的实例,该作用域仅在当前 HTTP Session 内有效。 - 5)global-session
作用于集群环境的会话范围(全局会话范围),当不是集群环境(Portlet)时,它就是普通session。
在上述五种作用域中,singleton
和 prototype
是最常用的两种。
1.2 singleton和prototype 作用域
singleton
作用域
是 Spring 容器默认的作用域,当一个 Bean 的作用域为singleton
时,Spring 容器中只会存在一个共享的 Bean 实例
,并且所有对 Bean 的请求,只要 id 与该 Bean 定义相匹配,就只会返回 Bean 的同一个实例
。
通常情况下,这种单例模式对于无会话状态的 Bean(如 DAO 层、Service 层)来说,是最理想的选择。prototype
作用域
使用prototype
作用域的 Bean 会在每次请求该 Bean 时都会创建一个新的 Bean 实例。因此对需要保持会话状态的 Bean应该使用prototype
作用域。
1.3 代码演示
在singleton和prototype文件内各建立一个实体类StudentOne和StudentTwo
public class StudentOne {
//默认构造方法
}
public class StudentTwo {
}
在 Spring 配置文件中,可以使用<bean>
元素的 scope
属性,将 Bean 的作用域定义成singleton/prototype
,其配置方式如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--scope = 单例-->
<bean id="StudentOne" class="com.dab.singleton.StudentOne" scope="singleton"></bean>
<!--scope = 多例-->
<bean id="StudentTwo" class="com.dab.prototype.StudentTwo" scope="prototype"></bean>
</beans>
测试类
public class Test {
public static void main(String[] args) {
//1.获取spring核心容器对象,加载配置文件
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
//2.根据id获取Bean对象
//输出获取实例StudentOne是单例对象
System.out.println("单例:");
System.out.println(ac.getBean("StudentOne"));
System.out.println(ac.getBean("StudentOne"));
System.out.println(ac.getBean("StudentOne"));//一样的对象实例
//输出获取实例StudentTwo是单例对象
System.out.println("多例:");
System.out.println(ac.getBean("StudentTwo"));
System.out.println(ac.getBean("StudentTwo"));
System.out.println(ac.getBean("StudentTwo"));//不一样的对象实例
}
}
运行结果:
1.4 小结
从运行结果可以看到,singleton
三次输出的结果相同,这说明 Spring 容器只创建了一个 StudentOne类的实例。由于 Spring 容器默认作用域是 singleton
,如果不设置 scope="singleton"
,则其输出结果也将是一个实例。prototype
三次输出的结果并不相同,这说明在prototype
作用域下,Spring 容器创建了多个不同的 Person 实例。
二. Spring Bean的生命周期
2.1 为什么要了解 Bean的生命周期
了解 Spring 生命周期的意义就在于,可以利用 Bean 在其存活期间的指定时刻完成一些相关操作。这种时刻可能有很多,但一般情况下,会在 Bean 被初始化后和被销毁前执行一些相关操作。
在 Spring 中,Bean 的生命周期是一个很复杂的执行过程,我们可以利用 Spring 提供的方法定制 Bean 的创建过程。
当一个 Bean
被加载到 Spring 容器时,它就具有了生命,而 Spring 容器在保证一个 Bean
能够使用之前,会进行很多工作。Spring 容器中 Bean
的生命周期流程如下图所示。
2.2 bean对象的生命周期
单例对象
- 出生:当容器创建时对象出生
- 活着:只要容器还在,对象一直活着
- 死亡:容器销毁,对象消亡
- 总结:单例对象的生命周期和容器相同
Spring 容器可以管理 singleton
作用域 Bean
的生命周期,在此作用域下,Spring 能够精确地知道该 Bean
何时被创建,何时初始化完成,以及何时被销毁。
多例对象
- 出生:当我们使用对象时spring框架为我们创建
- 活着:对象只要是在使用过程中就一直活着。
- 死亡:当对象长时间不用,且没有别的对象引用时,由Java的垃圾回收器回收
而对于 prototype
作用域的 Bean
,Spring 只负责创建,当容器创建了 Bean
的实例后,Bean
的实例就交给客户端代码管理,Spring 容器将不再跟踪其生命周期。每次客户端请求 prototype
作用域的 Bean
时,Spring 容器都会创建一个新的实例,并且不会管那些被配置成 prototype
作用域的 Bean
的生命周期。
2.3 代码演示
创建一个singleton实体类
public class singletonDemo {
public singletonDemo(){
System.out.println("单例对象创建了.");
}
public void method() {
System.out.println("singletonDemo中的method方法执行了。");
}
public void init(){
System.out.println("对象初始化了。。。");
}
public void destroy(){
System.out.println("对象销毁了。。。");
}
}
Spring 配置文件
属性:
- init-method:指定类中的初始化方法名称。
- destroy-method:指定类中销毁方法名称。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--
单例对象的生命周期
属性:
init-method:指定类中的初始化方法名称。
destroy-method:指定类中销毁方法名称。
-->
<bean id="singletonDemo" class="com.dab.singletonDemo" scope="singleton" init-method="init" destroy-method="destroy"></bean>
</beans>
测试类
public class Test {
public static void main(String[] args) {
//1.获取spring核心容器对象,加载配置文件
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
//2.根据id获取Bean对象
singletonDemo demoBean = (singletonDemo) ac.getBean("singletonDemo");
System.out.println(demoBean);
demoBean.method();
//手动关闭容器
ac.close();//关闭方法存在容器接口的实现类中
}
}
运行结果
2.4 小结
从结果可以看到,Spring 容器可以管理 singleton
作用域 Bean
的生命周期,可以进行一些对象初始化时的操作,像耗时资源获取;对象销毁时的操作,像释放资源。
推荐阅读
- Spring学习(1)-了解spring的各个模块.
- Spring学习(2)-程序间耦合和工厂模式解耦.
- Spring学习(3)-spring核心思想IOC(控制反转)和DI(依赖注入).
- Spring学习(4)-spring IOC中bean标签,常用属性,注入方法.
- Spring学习(5)-spring Bean的作用范围和生命周期.
- Spring学习(6)-spring简单例子.
欢迎点赞评论,指出不足,笔者由衷感谢o!