Spring的生命周期及Spring Bean单例和多例---超详细教学

一,何为spring生命周期    

    一个Bean对象从被Spring容器创建到被销毁的整个过程。Spring框架对Bean对象的生命周期进行了管理,提供了灵活性和控制权,让开发人员能够在不同的阶段进行自定义操作

1.1生命周期图

1.2.为什么要学习对象的生命周期?

1.2.1 定位和解决问题

     对象的生命周期可以帮助我们准确定位和解决程序中的问题。当程序出现 bug 或异常时,了解对象的生命周期可以帮助我们追踪问题所在,并在适当的阶段进行调试和修复。

1.2.2 资源管理

    对象的生命周期涉及到资源的分配和释放,如内存、数据库连接、文件等。了解对象的生命周期可以帮助我们更好地管理和优化资源的使用,避免资源泄漏或过度占用资源的情况发生。

1.2.3 性能优化

   了解对象的生命周期可以帮助我们优化程序的性能。通过有效地管理对象的创建和销毁,以及合理利用对象池、缓存等技术,可以减少不必要的资源消耗和提高程序的运行效率。

1.2.4 设计模式和架构

   对象的生命周期与设计模式和架构密切相关。学习对象的生命周期可以帮助我们更好地设计和实现面向对象的系统,选择合适的设计模式和架构来管理和组织对象,以实现可维护、可扩展和高效的系统

1.2.5 对象的状态管理

     对象的生命周期涉及到对象的状态转换和行为变化。了解对象的生命周期可以帮助我们更好地管理对象的状态,避免状态混乱或不一致的情况发生,以确保程序的正确性和可靠性

 1.3 生命周期大致流程

1. Spring启动,查找并加载需要被Spring管理的bean,进行Bean的实例化


2. Bean实例化后将Bean的引入和值注入到Bean的属性中


3. 如果Bean实现了BeanNameAware接口的话,Spring将Bean的id传递给setBeanName()方法
BeanNameAware的作用:让Bean获取自己在BeanFactory配置中的名字。


4. 如果Bean实现了BeanFactoryAware接口的话,Spring将调用setBeanFactory()方法,将BeanFactory容器实例传入
BeanFactoryAware的作用:让Bean获取配置他们的BeanFactory的引用。


5. 如果Bean实现了ApplicationContextAware接口的话,Spring将调用Bean的setApplicationContext()方法,将bean所在应用上下文引用传入
为什么使用ApplicationContextAware接口:在spring项目中,类之间的关系是spring容器来管理的,但是一个项目中有些类不受spring容器管理缺需要使用受spring管理的bean,这时候不能通过正常的方式注入bean,这时候spring给我们提供了ApplicationContextAware接口,我们可以编写一个工具类来实现ApplicationContextAware,通过工具类来获取我们需要的bean然后供不在spring容器中的类调用。


6. 如果Bean实现了BeanPostProcessor接口,Spring就将调用他们的postProcessBeforeInitialization()方法
postProcessBeforeInitialization()方法:初始化方法之前调用


7. 如果Bean实现了InitializingBean接口,Spring将调用他们的afterPropertiesSet()方法。类似的,如果bean使用init-method声明了初始化方法,该方法也会被调用
afterPropertiesSet()方法:初始化方法。如果使用了init-method声明了初始化方法,则执行顺序为:先执行afterPropertiesSet()方法,再执行init-method声明的方法。


8. 如果Bean实现了BeanPostProcessor接口,Spring就将调用他们的postProcessAfterInitialization()方法
postProcessAfterInitialization()方法:初始化方法之后调用


9. 此时,Bean已经准备就绪,可以被应用程序使用了。他们将一直驻留在应用上下文中,直到应用上下文被销毁


10. 如果bean实现了DisposableBean接口,Spring将调用它的destory()接口方法,同样,如果bean使用了destory-method 声明销毁方法,该方法也会被调用
destory()方法:销毁前调用。如果使用了destory-method声明了销毁方法,则执行顺序为:先执行destory()方法,再执行destory-method声明的方法。

二, Spring Bean的单例与多例的作用域

2.1 单例模式(Singleton):

  • 单例是指在整个应用程序上下文中只创建一个实例,并且所有的请求都会返回同一个实例
  • 默认情况下,Spring容器中的Bean都是单例的
  • 单例模式适用于那些不需要维护状态的Bean,或者对资源消耗较大的Bean进行共享

缺点:使用单例会有变量污染,单例是根据spring上下文初始化;容器生对象生,容器死对象死

2.2 多例模式(Prototype):

  • 多例是指每次请求时都会创建一个新的实例,每个实例都是独立的
  • 每次从容器中获取该Bean时,都会创建一个新的实例
  • 多例模式适用于那些需要维护状态的Bean,或者对资源消耗较小的Bean进行独立创建

缺点:使用多例及其消耗内存,多例使用时候才会创建,销毁跟着jvm走。

三  单例Bean与多例Bean的配置方式(两种)

3.1 注解方式:

// 使用注解配置单例Bean
@Component
@Scope("singleton")
public class MySingletonBean {// ...
}// 使用注解配置多例Bean
@Component
@Scope("prototype")
public class MyPrototypeBean {// ...
}

3.2  XML方式:

<!-- 使用XML配置单例Bean --><bean id="paramAction" class="com.zking.beanlife.ParamAction" scope="singleton"><!-- ... -->
</bean><!-- 使用XML配置多例Bean --><bean id="paramAction" class="com.zking.beanlife.ParamAction" scope="prototype"><!-- ... -->
</bean>

单例案例:

定义一个类,并创建三个方法

package com.zking.beanlife;public class InstanceFactory {public void init() {System.out.println("初始化方法");}public void destroy() {System.out.println("销毁方法");}public void service() {System.out.println("业务方法");}
}

后端Servlet

package com.zking.beanlife;import java.util.List;public class ParamAction {private int age;private String name;private List<String> hobby;private int num = 1;// private UserBiz userBiz = new UserBizImpl1();public ParamAction() {super();}public ParamAction(int age, String name, List<String> hobby) {super();this.age = age;this.name = name;this.hobby = hobby;}public void execute() {// userBiz.upload();// userBiz = new UserBizImpl2();System.out.println("this.num=" + this.num++);System.out.println(this.name);System.out.println(this.age);System.out.println(this.hobby);}
}

 

测试类:

package com.zking.beanlife;import org.junit.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;/** spring	bean的生命週期* spring	bean的單例多例*/
public class Demo2 {// 体现单例与多例的区别@Testpublic void test1() {ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("/spring-context.xml");
//		InstanceFactory   instanceFactory = (InstanceFactory) applicationContext.getBean("instanceFactory");//		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/spring-context.xml");ParamAction p1 = (ParamAction) applicationContext.getBean("paramAction");ParamAction p2 = (ParamAction) applicationContext.getBean("paramAction");
//		 System.out.println(p1==p2);p1.execute();p2.execute();//		单例时,容器销毁instanceFactory对象也销毁;多例时,容器销毁对象不一定销毁;applicationContext.close();}// 体现单例与多例的初始化的时间点 instanceFactory@Testpublic void test2() {ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/spring-context.xml");}// BeanFactory会初始化bean对象,但会根据不同的实现子类采取不同的初始化方式// 默认情况下bean的初始化,单例模式立马会执行,但是此时XmlBeanFactory作为子类,单例模式下容器创建,bean依赖没有初始化,只有要获取使用bean对象才进行初始化@Testpublic void test3() {// ClassPathXmlApplicationContext applicationContext = new// ClassPathXmlApplicationContext("/spring-context.xml");Resource resource = new ClassPathResource("/spring-context.xml");BeanFactory beanFactory = new XmlBeanFactory(resource);
//		InstanceFactory i1 = (InstanceFactory) beanFactory.getBean("instanceFactory");}}

spring Config文件的配置

 

运行结果:

 

这里的num值分别为1和2,则说明是单例的,单例模式即存在变量污染

多例案例:

 

运行结果:

 多例使用时候才会创建,销毁跟着jvm走

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/47591.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微人事 部门管理 模块 (十五)

部门管理的树展示和搜索 数据展示页是个树&#xff0c;我们一次性把数据加载出来也可以通过点一次id加载查询出来出来子部门&#xff0c;我们用一次拿到说有json数据加载出来 数据不多可以用递归&#xff0c;数据很多就用懒加载的方式 由于子部门比较深就不适合&#xff0c;权…

不负众望~历时4年修炼,这本册子终于成书了(文末赠书)

名字&#xff1a;阿玥的小东东 学习&#xff1a;Python、C/C 主页链接&#xff1a;阿玥的小东东的博客_CSDN博客-python&&c高级知识,过年必备,C/C知识讲解领域博主 目录 精进Spring Boot首选读物 “小册”变“大书”&#xff0c;彻底弄懂Spring Boot 全方位配套资源…

STL——list用法

一、list介绍 1、list是可以在常数范围内在任意位置进行插入和删除的序列式容器&#xff0c;并且该容器可以前后双向迭代。 2、list就是一个带头双向循环链表&#xff0c;list通常在任意位置进行插入、移除元素的执行效率更好。 3、list最大的缺陷是不支持任意位置的随机访问…

等保测评--安全物理环境--测评方法

安全子类--物理位置选择 a)机房场地应选择在具有防震、防风和防雨等能力的建筑内; 一、测评对象 记录类文档和机房 二、测评实施 1)检查机房所在建筑物是否具有建筑物抗震设防审批文档; 2)检查机房门窗是否不存在因风导致的尘土严重; 3)检查机房是否不存在雨水渗漏…

【BASH】回顾与知识点梳理(三十六)

【BASH】回顾与知识点梳理 三十六 三十六. 认识与分析登录档36.1 什么是登录档CentOS 7 登录档简易说明登录档的重要性Linux 常见的登录档档名登录档所需相关服务 (daemon) 与程序CentOS 7.x 使用 systemd 提供的 journalctl 日志管理 登录档内容的一般格式 36.2 rsyslog.servi…

makefile的自动化变量

一、是什么? 自动化变量:makefile依据执行的规则自动变化生成的变量 $(@) 规则的目标文件名 $(^) 所有依赖 依赖列表 $(<)第一个依赖文件名 $(*)规则中目标中%部分名 $(?)所有比目标文件更新的依赖文件列表,空格分隔 二、使用步骤 1.引入库 代码如下(示例): make …

QPushbutton

QPushbutton API使用方式 QPushbutton大部分时候都需要使用它从父类QAbstractbutton中继承过来的那些 API。 API // 构造函数 /* 参数:- icon: 按钮上显示的图标- text: 按钮上显示的标题- parent: 按钮的父对象, 可以不指定 */ QPushButton::QPushButton(const QIcon &i…

Lua + Redis 实战代码

--[[luarocks install luasocket module socket not foundhttps://github.com/nrk/redis-lua最历害的是&#xff0c;用redis 去跑lua&#xff0c;分布式锁&#xff0c;限流&#xff0c;]]--local redis require("redis");local config{host"127.0.0.1&…

基于STM32+FreeRTOS的四轴机械臂

目录 代码&#xff1a; 注释写的较少&#xff0c;但本文出现的代码都有注释&#xff0c;所以请直接在本文里看注释 项目概述&#xff1a; 一 准备阶段&#xff08;都是些废话&#xff09; 二 裸机测试功能 1.摇杆控制 接线&#xff1a; CubeMX配置&#xff1a; 代码 2…

解决conda activate报错

解决方法 source ~/anaconda3/bin/activate或 source ~/miniconda3/bin/activate然后就可以使用 conda activate xxx环境了 问题解析 请参考github&#xff1a;https://github.com/conda/conda/issues/7980

深入探索代理技术:Socks5、IP代理与网络安全

在当今高度互联的世界中&#xff0c;代理技术在网络安全和爬虫等领域发挥着重要作用。本文将着重介绍Socks5代理、IP代理以及它们在网络安全与爬虫开发中的应用&#xff0c;旨在帮助读者深入理解这些技术&#xff0c;从而更好地应用于实际情境。 1. Socks5代理的特点与用途 S…

redis7高级篇2 redis的BigKey的处理

一 Bigkey的处理 1.1 模拟造数 1.截图 2.代码 &#xff1a;使用pipe 批量插入10w的数据量 cat /root/export/monidata.txt | redis-cli -h 127.0.0.1 -a 123456 -p 6379 --pipe [rootlocalhost export]# for((i1;i<10*10;i)); do echo "set k$i v$i" >>…

常见的 Web API

以下是一些常见的 Web API 列表&#xff1a; DOM API&#xff1a;用于操作和操纵网页的文档对象模型。 XMLHttpRequest&#xff1a;用于发送 HTTP 请求&#xff0c;并与服务器进行通信。 Fetch API&#xff1a;用于发送网络请求&#xff0c;并处理响应。 Web Storage API&…

python的上下文管理器

上下文管理器(Context managers) 上下文管理器允许你在有需要的时候&#xff0c;精确地分配和释放资源。 使用上下文管理器最广泛的案例就是with语句了。 想象下你有两个需要结对执行的相关操作&#xff0c;然后还要在它们中间放置一段代码。 上下文管理器就是专门让你做这种…

go gorm 查询

定义model package mysqltestimport ("errors""fmt""gorm.io/gorm" )type Product struct {gorm.ModelID uint gorm:"primarykey"Name string gorm:"column:name"Price float64 gorm:"column:price_value&quo…

【学习笔记之vue】 Cannot find module ‘node-sass‘

Cannot find module node-sass方案一&#xff08;不通&#xff09; 下载node-sass组件 >> npm install -g cnpm>>cnpm install node-sass下载时报错 方案二 使用npm下载node-sass组件 >>npm install node-sassok

安防视频监控平台EasyCVR视频集中存储平台接入RTSP设备出现离线情况的问题解决方案

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安…

Ubuntu 20系统WIFI设置静态IP地址,以及断连问题

​最近工作需要购置了一台GPU机器&#xff0c;然后搭建了深度学习的运行环境&#xff0c;在工作中将这台机器当做深度学习的服务器来使用&#xff0c;前期已经配置好多用户以及基础环境。但最近通过xshell连接总是不间断的出现断连现象。 补充一点&#xff0c;Ubuntu系统中与网…

Android设置顶部状态栏颜色

Android设置顶部状态栏颜色_wx637304bacd051的技术博客_51CTO博客

docker服务器、以及容器设置自动启动

一、docker服务设置自动启动 查看已启动的服务 systemctl list-units --typeservice 查看是否设置开机启动 systemctl list-unit-files | grep enable设置开机启动 systemctl enable docker.service关闭开机启动 systemctl disable docker.service 二、docker容器设置自…