0871-64605728
您当前位置:网站首页 >> 知识专区
Spring中Bean的作用域与生命周期
文章来源:CSDN 灰小猿  上传时间:2021-7-15  浏览量:758

  版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

目录

一、Bean的作用域

1、单实例Bean声明

2、多实例Bean声明

二、Bean的生命周期

1、bean的初始和销毁

2、bean的后置处理器


Hello,你好呀,我是灰小猿!一个超会写bug的程序猿!

在利用Spring进行IOC配置时,关于bean的配置和使用一直都是比较重要的一部分,同时如何合理的使用和创建bean对象,也是小伙伴们在学习和使用Spring时需要注意的部分,所以这一篇文章我就来和大家讲一下有关Spring中bean的作用域和其生命周期。

一、Bean的作用域

首先我们来讲一下有关于bean的作用域,

一般情况下,我们书写在IOC容器中的配置信息,会在我们的IOC容器运行时被创建,这就导致我们通过IOC容器获取到bean对象的时候,往往都是获取到了单实例的Bean对象,

这样就意味着无论我们使用多少个getBean()方法,获取到的同一个JavaBean都是同一个对象,这就是单实例Bean,整个项目都会共享这一个bean对象。

在Spring中,可以在<bean>元素的scope属性里设置bean的作用域,以决定这个bean是单实例的还是多实例的。Scope属性有四个参数,具体的使用可以看下图:

1、单实例Bean声明

默认情况下,Spring只为每个在IOC容器里声明的bean创建唯一一个实例,整个IOC容器范围内都能共享该实例:所有后续的getBean()调用和bean引用都将返回这个唯一的bean实例。该作用域被称为singleton,它是所有bean的默认作用域。也就是单实例。

为了验证这一说法,我们在IOC中创建一个单实例的bean,并且获取该bean对象进行对比:

			
  1. <!-- singleton单实例bean
  2. 1、在容器创建时被创建
  3. 2、只有一个实例
  4. -->
  5. <bean id="book02" class="com.spring.beans.Book" scope="singleton"></bean>

测试获取到的单实例bean是否是同一个:

			
  1. @Test
  2. public void test09() {
  3. // 单实例创建时创建的两个bean相等
  4. Book book03 = (Book)iocContext3.getBean("book02");
  5. Book book04 = (Book)iocContext3.getBean("book02");
  6. System.out.println(book03==book04);
  7. }

得到的结果是true;

2、多实例Bean声明

而既然存在单实例,那么就一定存在多实例。我们可以为bean对象的scope属性设置prototype参数,以表示该实例是多实例的,同时获取IOC容器中的多实例bean,再将获取到的多实例bean进行对比,

			
  1. <!-- prototype多实例bean
  2. 1、在容器创建时不会被创建,
  3. 2、只有在被调用的时候才会被创建
  4. 3、可以存在多个实例
  5. -->
  6. <bean id="book01" class="com.spring.beans.Book" scope="prototype"></bean>

测试获取到的多实例bean是否是同一个:

			
  1. @Test
  2. public void test09() {
  3. // 多实例创建时,创建的两个bean对象不相等
  4. Book book01 = (Book)iocContext3.getBean("book01");
  5. Book book02 = (Book)iocContext3.getBean("book01");
  6. System.out.println(book01==book02);
  7. }

得到的结果是false

这就说明了,通过多实例创建的bean对象是各不相同的。

在这里需要注意:

同时关于单实例和多实例bean的创建也有不同,当bean的作用域为单例时,Spring会在IOC容器对象创建时就创建bean的对象实例。而当bean的作用域为prototype时,IOC容器在获取bean的实例时创建bean的实例对象。

二、Bean的生命周期

1、bean的初始和销毁

其实我们在IOC中创建的每一个bean对象都是有其特定的生命周期的,在Spring的IOC容器中可以管理bean的生命周期,Spring允许在bean生命周期内特定的时间点执行指定的任务。如在bean初始化时执行的方法和bean被销毁时执行的方法。

Spring IOC容器对bean的生命周期进行管理的过程可以分为六步:

  1. 通过构造器或工厂方法创建bean实例
  2. 为bean的属性设置值和对其他bean的引用
  3. 调用bean的初始化方法
  4. bean可以正常使用
  5. 当容器关闭时,调用bean的销毁方法

那么关于bean的初始和销毁时执行的方法又该如何声明呢?

首先我们应该在bean类内部添加初始和销毁时执行的方法。如下面这个javabean:

			
  1. package com.spring.beans;
  2. public class Book {
  3. private String bookName;
  4. private String author;
  5. /**
  6. * 初始化方法
  7. * */
  8. public void myInit() {
  9. System.out.println("book bean被创建");
  10. }
  11. /**
  12. * 销毁时方法
  13. * */
  14. public void myDestory() {
  15. System.out.println("book bean被销毁");
  16. }
  17. public String getBookName() {
  18. return bookName;
  19. }
  20. public void setBookName(String bookName) {
  21. this.bookName = bookName;
  22. }
  23. public String getAuthor() {
  24. return author;
  25. }
  26. public void setAuthor(String author) {
  27. this.author = author;
  28. }
  29. @Override
  30. public String toString() {
  31. return "Book [bookName=" + bookName + ", author=" + author + "]";
  32. }
  33. }

这时我们在配置bean时,可以通过init-method和destroy-method 属性为bean指定初始化和销毁方法,

			
  1. <!-- 设置bean的生命周期
  2. destory-method:结束调用的方法
  3. init-method:起始时调用的方法
  4. -->
  5. <bean id="book01" class="com.spring.beans.Book" destroy-method="myDestory" init-method="myInit"></bean>

 这样当我们在通过IOC容器创建和销毁bean对象时就会执行相应的方法,

但是这里还是有一点需要注意:

我们上面说了,单实例的bean和多实例的bean的创建时间是不同的,那么他们的初始方法和销毁方法的执行时间就稍稍有不同。

单实例下 bean的生命周期

容器启动——>初始化方法——>(容器关闭)销毁方法

多实例下 bean的生命周期

容器启动——>调用bean——>初始化方法——>容器关闭(销毁方法不执行)

2、bean的后置处理器

什么是bean的后置处理器?bean后置处理器允许在调用初始化方法前后对bean进行额外的处理

bean后置处理器对IOC容器里的所有bean实例逐一处理,而非单一实例。

其典型应用是:检查bean属性的正确性或根据特定的标准更改bean的属性。

bean后置处理器使用时需要实现接口:

org.springframework.beans.factory.config.BeanPostProcessor。

在初始化方法被调用前后,Spring将把每个bean实例分别传递给上述接口的以下两个方法:

postProcessBeforeInitialization(Object, String)调用前

postProcessAfterInitialization(Object, String)调用后

如下是一个实现在该接口的后置处理器:

			
  1. package com.spring.beans;
  2. import org.springframework.beans.BeansException;
  3. import org.springframework.beans.factory.config.BeanPostProcessor;
  4. /**
  5. * 测试bean的后置处理器
  6. * 在这里要注意一点是为了出现bean和beanName,而不是arg0、arg1,需要绑定相应的源码jar包
  7. * */
  8. public class MyBeanPostProcessor implements BeanPostProcessor{
  9. /**
  10. * postProcessBeforeInitialization
  11. * 初始化方法执行前执行
  12. * Object bean
  13. * String beanName xml容器中定义的bean名称
  14. * */
  15. @Override
  16. public Object postProcessBeforeInitialization(Object bean, String beanName)
  17. throws BeansException {
  18. // TODO Auto-generated method stub
  19. System.out.println("【"+ beanName+"】初始化方法执行前...");
  20. return bean;
  21. }
  22. /**
  23. * postProcessAfterInitialization
  24. * 初始化方法执行后执行
  25. * Object bean
  26. * String beanName xml容器中定义的bean名称
  27. * */
  28. @Override
  29. public Object postProcessAfterInitialization(Object bean, String beanName)
  30. throws BeansException {
  31. // TODO Auto-generated method stub
  32. System.out.println("【"+ beanName+"】初始化方法执行后...");
  33. return bean;
  34. }
  35. }

将该后置处理器加入到IOC容器中:

			
  1. <!-- 测试bean的后置处理器 -->
  2. <bean id="beanPostProcessor" class="com.spring.beans.MyBeanPostProcessor"></bean>

由于现在我们的bean对象是单实例的,所以容器运行时就会直接创建bean对象,同时也会执行该bean的后置处理器方法和初始化方法,在容器被销毁时又会执行销毁方法。我们测试如下:

			
  1. //*************************bean生命周期*****************
  2. // 由于ApplicationContext是一个顶层接口,里面没有销毁方法close,所以需要使用它的子接口进行接收
  3. ConfigurableApplicationContext iocContext01 = new ClassPathXmlApplicationContext("ioc1.xml");
  4. @Test
  5. public void test01() {
  6. iocContext01.getBean("book01");
  7. iocContext01.close();
  8. }

运行结果:

总结一下后置处理器的执行过程:

  1. 通过构造器或工厂方法创建bean实例
  2. 为bean的属性设置值和对其他bean的引用
  3. 将bean实例传递给bean后置处理器的postProcessBeforeInitialization()方法
  4. 调用bean的初始化方法
  5. 将bean实例传递给bean后置处理器的postProcessAfterInitialization()方法
  6. bean可以使用了
  7. 当容器关闭时调用bean的销毁方法

所以添加bean后置处理器后bean的生命周期为:

容器启动——后置处理器的before...——>初始化方法——>后置处理器的after...———>(容器关闭)销毁方法


29

2021-06

python自制一款职位分析器,一键生成岗位分析报告

python自制一款职位分析器,一键生成岗位分析报告

15

2021-01

1.6 万亿参数你怕了吗?谷歌大脑语言模型速度是 T5 速度的 7 倍

四个参数,我就能拟合出一个大象出来,用五个参数我就能让他的鼻子摆动

25

2021-01

支持 RISC-V 芯片的 Android 系统来了!

支持 RISC-V 芯片的 Android 系统来了!

04

2022-03

干掉Session?这个跨域认证解决方案真的优雅

干掉Session?这个跨域认证解决方案真的优雅

26

2021-04

LiteOS内核源码分析:消息队列Queue

LiteOS内核源码分析:消息队列Queue

20

2021-08

❤️使用 HTML、CSS 和 JavaScript 的简单模拟时钟❤️

❤️使用 HTML、CSS 和 JavaScript 的简单模拟时钟❤️

21

2021-04

3D 语义分割、目标检测、实例分割。TF 3D 技术让你一目了然

3D 语义分割、目标检测、实例分割是什么神仙操作?TF 3D 技术让你一目了然

18

2022-02

Redis6-雪崩、击穿、穿透、分布式锁

Redis6-雪崩、击穿、穿透、分布式锁
返回顶部
客服电话
0871-64605728
用微信扫一扫关注我们
请各公司推销人员注意:我单位拒绝任何方式、任何形式的电话推销,请勿拔打我单位客服热线进行电话推销,谢谢合作!
公司名称:云南昂略科技有限公司
联系地址:云南省昆明市官渡区永平路188号鑫都韵城写字楼6栋1004号
联系电话:0871-64605728、传真号码:0871-64605728
电子邮箱:19701580@qq.com
关键词:知识专区:Spring中Bean的作用域与生命周期,云南昂略科技有限公司,云南移动执法平台建设,云南智慧安防调度系统,云南头戴式安全终端,昂略科技
云南网站建设,云南网页设计,昆明网站建设,昆明网页设计  网站管理
【版权声明】本站部分内容由互联网用户自行发布,著作权或版权归原作者所有。如果侵犯到您的权益请发邮件致info@ynjwz.com,我们会第一时间进行删除并表示歉意。