Spring中Bean的作用域和生命周期
作用域的种类
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
在一个全局的 HTTP Session 中,容器会返回该 Bean 的同一个实例。该作用域仅在使用 portlet context 时有效。
在上述五种作用域中,singleton 和 prototype 是最常用的两种,接下来将对这两种作用域进行详细讲解。
singleton 作用域
singleton 是 Spring 容器默认的作用域,当一个 Bean 的作用域为 singleton 时,Spring 容器中只会存在一个共享的 Bean 实例,并且所有对 Bean 的请求,只要 id 与该 Bean 定义相匹配,就只会返回 Bean 的同一个实例。
通常情况下,这种单例模式对于无会话状态的 Bean(如 DAO 层、Service 层)来说,是最理想的选择。
在 Spring 配置文件中,可以使用 <bean> 元素的 scope 属性,将 Bean 的作用域定义成 singleton,其配置方式如下所示:
<bean id="person" class="com.mengma.scope.Person" scope="singleton"/>
在项目的 src 目录下创建一个名为 com.mengma.scope 的包,在该包下创建 Person 类,类中不需要添加任何成员,然后创建 Spring 的配置文件 applicationContext.xml,将上述 Bean 的定义方式写入配置文件中,最后创建一个名为 PersonTest 的测试类,编辑后如下所示。
package com.mengma.scope; import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; public class PersonTest {
@Test
public void test() {
// 定义Spring配置文件路径
String xmlPath = "com/mengma/scope/applicationContext.xml";
// 初始化Spring容器,加载配置文件,并对bean进行实例化
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
xmlPath);
// 输出获得实例
System.out.println(applicationContext.getBean("person"));
System.out.println(applicationContext.getBean("person"));
}
}
使用 JUnit 测试运行 test() 方法,运行成功后,控制台的输出结果如图 1 所示。

图 1 输出结果
从图 1 中可以看到,两次输出的结果相同,这说明 Spring 容器只创建了一个 Person 类的实例。由于 Spring 容器默认作用域是 singleton,如果不设置 scope="singleton",则其输出结果也将是一个实例。
prototype 作用域
使用 prototype 作用域的 Bean 会在每次请求该 Bean 时都会创建一个新的 Bean 实例。因此对需要保持会话状态的 Bean(如 Struts2 的 Action 类)应该使用 prototype 作用域。
在 Spring 配置文件中,要将 Bean 定义为 prototype 作用域,只需将 <bean> 元素的 scope 属性值定义成 prototype,其示例代码如下所示:
<bean id="person" class="com.mengma.scope.Person" scope="prototype"/>
将《singleton作用域》部分中的配置文件更改成上述代码形式后,再次运行 test() 方法,控制台的输出结果如图 2 所示。

图 2 输出结果
从图 2 的输出结果中可以看到,两次输出的结果并不相同,这说明在 prototype 作用域下,Spring 容器创建了两个不同的 Person 实例。
生命周期
而对于 prototype 作用域的 Bean,Spring 只负责创建,当容器创建了 Bean 的实例后,Bean 的实例就交给客户端代码管理,Spring 容器将不再跟踪其生命周期。每次客户端请求 prototype 作用域的 Bean 时,Spring 容器都会创建一个新的实例,并且不会管那些被配置成 prototype 作用域的 Bean 的生命周期。
了解 Spring 生命周期的意义就在于,可以利用 Bean 在其存活期间的指定时刻完成一些相关操作。这种时刻可能有很多,但一般情况下,会在 Bean 被初始化后和被销毁前执行一些相关操作。
在 Spring 中,Bean 的生命周期是一个很复杂的执行过程,我们可以利用 Spring 提供的方法定制 Bean 的创建过程。
当一个 Bean 被加载到 Spring 容器时,它就具有了生命,而 Spring 容器在保证一个 Bean 能够使用之前,会进行很多工作。Spring 容器中 Bean 的生命周期流程如图 1 所示。

图 1 Bean 的生命周期
Bean 生命周期的整个执行过程描述如下。
1)根据配置情况调用 Bean 构造方法或工厂方法实例化 Bean。
2)利用依赖注入完成 Bean 中所有属性值的配置注入。
3)如果 Bean 实现了 BeanNameAware 接口,则 Spring 调用 Bean 的 setBeanName() 方法传入当前 Bean 的 id 值。
4)如果 Bean 实现了 BeanFactoryAware 接口,则 Spring 调用 setBeanFactory() 方法传入当前工厂实例的引用。
5)如果 Bean 实现了 ApplicationContextAware 接口,则 Spring 调用 setApplicationContext() 方法传入当前 ApplicationContext 实例的引用。
6)如果 BeanPostProcessor 和 Bean 关联,则 Spring 将调用该接口的预初始化方法 postProcessBeforeInitialzation() 对 Bean 进行加工操作,此处非常重要,Spring 的 AOP 就是利用它实现的。
7)如果 Bean 实现了 InitializingBean 接口,则 Spring 将调用 afterPropertiesSet() 方法。
8)如果在配置文件中通过 init-method 属性指定了初始化方法,则调用该初始化方法。
9)如果 BeanPostProcessor 和 Bean 关联,则 Spring 将调用该接口的初始化方法 postProcessAfterInitialization()。此时,Bean 已经可以被应用系统使用了。
10)如果在 <bean> 中指定了该 Bean 的作用范围为 scope="singleton",则将该 Bean 放入 Spring IoC 的缓存池中,将触发 Spring 对该 Bean 的生命周期管理;如果在 <bean> 中指定了该 Bean 的作用范围为 scope="prototype",则将该 Bean 交给调用者,调用者管理该 Bean 的生命周期,Spring 不再管理该 Bean。
11)如果 Bean 实现了 DisposableBean 接口,则 Spring 会调用 destory() 方法将 Spring 中的 Bean 销毁;如果在配置文件中通过 destory-method 属性指定了 Bean 的销毁方法,则 Spring 将调用该方法对 Bean 进行销毁。
Spring 为 Bean 提供了细致全面的生命周期过程,通过实现特定的接口或 <bean> 的属性设置,都可以对 Bean 的生命周期过程产生影响。虽然可以随意配置 <bean> 的属性,但是建议不要过多地使用 Bean 实现接口,因为这样会导致代码和 Spring 的聚合过于紧密。
Spring中Bean的作用域和生命周期的更多相关文章
- 详解Spring中Bean的作用域与生命周期
摘要:在利用Spring进行IOC配置时,关于bean的配置和使用一直都是比较重要的一部分,同时如何合理的使用和创建bean对象,也是小伙伴们在学习和使用Spring时需要注意的部分,所以这一篇文章我 ...
- Spring中Bean的作用域、生命周期
Bean的作用域.生命周期 Bean的作用域 Spring 3中为Bean定义了5中作用域,分别为singleton(单例).protot ...
- Spring中bean的作用域与生命周期
在 Spring 中,那些组成应用程序的主体及由 Spring IOC 容器所管理的对象,被称之为 bean.简单地讲,bean 就是由 IOC 容器初始化.装配及管理的对象,除此之外,bean 就与 ...
- Spring之Bean的作用域与生命周期
在前面博客中提到容器启动获得BeanDefinition对象中有一个scope 属性.该属性控制着bean对象的作用域.本章节介绍Bean的作用域及生命周期,了解bean是怎么来的又怎么没的. 一.B ...
- 阶段3 2.Spring_03.Spring的 IOC 和 DI_8 spring中bean的细节之生命周期
区分单例还是多例对象 单例的几个状态 初始化方法和销毁方法 设置成我们定义的方法 测试 有创建和初始化.但是没有销毁,.对象一直没有销毁的方法 main方法是一切应用程序的入门.当main方法结束后. ...
- spring中bean的作用域属性singleton与prototype的区别
1.singleton 当一个bean的作用域设置为singleton, 那么Spring IOC容器中只会存在一个共享的bean实例,并且所有对bean的请求,只要id与该bean定义相匹配,则只会 ...
- C/C++——C++变量的作用域与生命周期,C语言中变量的作用域和生命周期
全局变量 作用域:全局作用域(全局变量只需在一个源文件中定义,就可以作用于所有的源文件.) 生命周期:程序运行期一直存在 引用方法:其他文件中要使用必须用extern 关键字声明要引用的全局变量. 内 ...
- Spring入门(五):Spring中bean的作用域
1. Spring中bean的多种作用域 在默认情况下,Spring应用上下文中所有的bean都是以单例(singleton)的形式创建的,即不管给定的一个bean被注入到其他bean多少次,每次所注 ...
- java——spring中bean的作用域
文章:理解Spring框架中Bean的作用域 博客地址:https://baijiahao.baidu.com/s?id=1610298792072480906&wfr=spider& ...
随机推荐
- HTML/CSS点滴记录
1. overflow 定义溢出元素内容区的内容会如何处理 visible 默认值.内容不会被修剪,会呈现在元素框之外. hidden 内容会被修剪,并且其余内容是不可见的. scroll 内容会被修 ...
- 微信小程序这一块(续)
1.设置头部的信息 通过wx.setNavigationBarTitle 详情见:https://developers.weixin.qq.com/miniprogram/dev/api/ui/nav ...
- Vue-实现简单拖拽(自定义属性)
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"& ...
- jQuery基础--动画操作
三组基本动画 <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset=" ...
- 什么是php扩展
PHP扩展英文为PHP Extension and Application Repository,简称pear(下面都以pear简称),中文全称为PHP扩展与应用库.是为了创建一个类似于Perl CP ...
- Java双链表
一.概述 二.英雄类 class HeroNode { //值域 public int id; public String name; public String nickName; //指针域 pu ...
- python 注释有哪些和作用
python 单行注释 #作为代表 python 多行注释 ‘’‘ 这是三个单引号注释 ’‘’ “”“ 这是三个双引号注释 ”“”
- NHibernet 事务 修改操作,事务没提交,数据库数据却同步(修改)了
Nhibernet 缓存 由于查询出来的数据和缓存关联,更新之后就算事务没执行提交操作,数据库依旧会更新,解决方法, 清空缓存,实例不和缓存关联,如下面标红代码 public bool UpdateT ...
- java ArrayList的几种方法使用
package java06; import java.util.ArrayList; /* ArrayList的常用的几个方法: public boolean add(E e) : 向集合汇总添加元 ...
- java ajax返回 Json 的 几种方式
原文:https://blog.csdn.net/qq_26289533/article/details/78749057 方式 1. : 自写代码转 Json 需要 HttpHttpServlet ...