Spring-4-掌握Spring事务传播机制
今日目标
能够掌握Spring事务配置
Spring事务管理
1 Spring事务简介【重点】
1.1 Spring事务作用
-
事务作用:在数据层保障一系列的数据库操作同成功同失败
-
Spring事务作用:在数据层或业务层保障一系列的数据库操作同成功同失败
1.2 案例分析Spring事务
-
需求:实现任意两个账户间转账操作
-
需求微缩:A账户减钱,B账户加钱
-
分析: ①:数据层提供基础操作,指定账户减钱(outMoney),指定账户加钱(inMoney) ②:业务层提供转账操作(transfer),调用减钱与加钱的操作 ③:提供2个账号和操作金额执行转账操作 ④:基于Spring整合MyBatis环境搭建上述操作
-
结果分析: ①:程序正常执行时,账户金额A减B加,没有问题 ②:程序出现异常后,转账失败,但是异常之前操作成功,异常之后操作失败,整体业务失败
-
结构:
1.3 代码实现
【前置工作】环境准备
创建数据库和表
CREATE DATABASE IF NOT EXISTS `spring_db2` DEFAULT CHARACTER SET utf8
USE `spring_db2`;DROP TABLE IF EXISTS `tbl_account`;
CREATE TABLE `tbl_account` (`id` INT(11) NOT NULL AUTO_INCREMENT,`name` VARCHAR(20) DEFAULT NULL,`money` DOUBLE DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;INSERT INTO `tbl_account`(`id`,`name`,`money`) VALUES
(1,'Jack',1000),
(2,'Rose',1000);DROP TABLE IF EXISTS `tbl_log`;
CREATE TABLE `tbl_log` (`id` INT(11) NOT NULL AUTO_INCREMENT,`info` VARCHAR(255) DEFAULT NULL,`create_date` DATETIME DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;INSERT INTO `tbl_log`(`id`,`info`,`create_date`) VALUES
(2,'Jack向Rose转账520.0元','2021-11-04 17:19:18');
pom.xml添加依赖
<dependencies><!--导入spring的坐标spring-context,对应版本是5.2.10.RELEASE--><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.3.15</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.28</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.3.15</version></dependency>
<!--mysql--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.27</version></dependency><!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.13</version></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>1.3.0</version></dependency><!-- https://mvnrepository.com/artifact/com.alibaba/druid --><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.18</version></dependency><!--junit,spring对junit4的要求必须是4.12版本以上--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13</version><scope>test</scope></dependency><!--spring-test--><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>5.3.22</version><scope>test</scope></dependency></dependencies>
Spring整合Mybatis相关代码(依赖、JdbcConfig、MybatisConfig、SpringConfig) JdbcConfig
package com.zbbmeta.config;import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;import javax.sql.DataSource;public class JdbcConfig {@Value("${jdbc.driverClassName}")private String driverClassName;@Value("${jdbc.url}")private String url;@Value("${jdbc.username}")private String userName;@Value("${jdbc.password}")private String password;@Beanpublic DataSource dataSource(){DruidDataSource ds = new DruidDataSource();ds.setDriverClassName(driverClassName);ds.setUrl(url);ds.setUsername(userName);ds.setPassword(password);return ds;}//spring提供的事务切面类:里面增强了事务管理功能,里面有事务提交和事务回滚功能@Beanpublic PlatformTransactionManager transactionManager(DataSource dataSource){DataSourceTransactionManager ptm = new DataSourceTransactionManager();ptm.setDataSource(dataSource);return ptm;}
}
MybatisConfig
package com.zbbmeta.config;import org.apache.ibatis.logging.stdout.StdOutImpl;
import org.apache.ibatis.session.Configuration;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.context.annotation.Bean;import javax.sql.DataSource;public class MybatisConfig {@Bean //不仅可以将返回值加入IOC容器,而且可以实现方法参数进行依赖注入,参数默认会根据类型从IOC容器中获取对象自动注入public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource){SqlSessionFactoryBean ssfb = new SqlSessionFactoryBean();ssfb.setTypeAliasesPackage("com.zbbmeta.entity"); //告诉mybatis,设置实体类包别名ssfb.setDataSource(dataSource); //将IOC容器中连接池给到Mybatis//注意:必须导入org.apache.ibatis.session.Configuration;Configuration configuration = new Configuration();//设置整合mybatis驼峰命名映射configuration.setMapUnderscoreToCamelCase(true);//设置打印日志configuration.setLogImpl(StdOutImpl.class);ssfb.setConfiguration(configuration);return ssfb;}
}
SpringConfig
@Configuration
@ComponentScan("com.zbbmeta")
@PropertySource("classpath:jdbc.properties")
@Import({JdbcConfig.class,MybatisConfig.class})
public class SpringConfig {
}
Account
@ToString
@Data
public class Account {private Integer id;private String name;private Double money;}
AccountDao
public interface AccountDao {@Update("update tbl_account set money = money + #{money} where name = #{name}")void inMoney(@Param("name") String name, @Param("money") Double money);@Update("update tbl_account set money = money - #{money} where name = #{name}")void outMoney(@Param("name") String name, @Param("money") Double money);
}
public interface AccountService {/*** 转账操作* @param out 传出方* @param in 转入方* @param money 金额*/void transfer(String out,String in,Double money) ;
}
AccountServiceImpl
@Service
public class AccountServiceImpl implements AccountService {@Autowiredprivate AccountDao accountDao;public void transfer(String out, String in, Double money) {//转出accountDao.outMoney(out, money);//模拟出现异常//System.out.println(1 / 0);//转入accountDao.inMoney(in, money);System.out.println("转账成功");}
}
【第一步】在业务层接口上添加Spring事务管理
在转账的方法上添加@Transactional注解
/*** 业务接口*/
public interface AccountService {/*** 转账操作* @param out 传出方* @param in 转入方* @param money 金额*/@Transactionalvoid transfer(String out,String in ,Double money) ;
}
注意事项
-
Spring注解式事务通常添加在业务层接口中而不会添加到业务层实现类中,降低耦合
-
注解式事务可以添加到业务方法上表示当前方法开启事务,也可以添加到接口上表示当前接口所有方法开启事务
【第二步】设置事务管理器(将事务管理器添加到IOC容器中)
说明:可以在JdbcConfig中配置事务管理器
//配置事务管理器,mybatis使用的是jdbc事务
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource){DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();transactionManager.setDataSource(dataSource);return transactionManager;
}
注意事项
-
事务管理器要根据实现技术进行选择
-
MyBatis框架使用的是JDBC事务
【第三步】开启注解式事务驱动
@EnableTransactionManagement
@Configuration
@ComponentScan("com.itheima")
@PropertySource("classpath:jdbc.properties")
@Import({JdbcConfig.class,MybatisConfig.class})
@EnableTransactionManagement //开启事务注解扫描
public class SpringConfig {
}
【第四步】运行测试类,查看结果
-
去掉@EnableTransactionManagement注解,即没有进行事务管理,当转账出现问题时结果
-
加上@EnableTransactionManagement注解,账户钱都恢复成1000
结果
-
转账成功的时候
结果:
@RunWith(SpringJUnit4ClassRunner.class) //指定第三方的运行器
@ContextConfiguration(classes = SpringConfig.class) //读取类配置文件
public class AccountDaoTest {@Autowired //自动注入业务对象private AccountService accountService;@Testpublic void testFindById() throws IOException {//直接使用业务方法accountService.transfer("Jack","Rose", 100d);}
}
2 Spring事务角色【理解】
问题导入
什么是事务管理员,什么是事务协调员?
2.1 Spring事务角色
-
事务管理员:发起事务方,在Spring中通常指代业务层开启事务的方法
-
事务协调员:加入事务方,在Spring中通常指数据层方法,也可以是业务层方法
3 Spring事务相关配置
问题导入
什么样的异常,Spring事务默认是不进行回滚的?
3.1 @Transactional注解中与事务相关配置
属性 | 作用 | 示例 | |
---|---|---|---|
readOnly | 设置是否为只读事务 | readOnly=true 只读事务 | |
timeout | 设置事务超时时间 | timeout = -1(永不超时) | |
rollbackFor | 设置事务回滚异常(class) | rollbackFor = {FileNotFoundException.class} | |
rollbackForClassName | 设置事务回滚异常(String) | 同上格式为字符串 | |
noRollbackFor | 设置事务不回滚异常(class) | noRollbackFor = {FileNotFoundException.class} | |
noRollbackForClassName | 设置事务不回滚异常(String) | 同上格式为字符串 | |
propagation | 设置事务传播行为 | …… |
属性 | 作用 | 示例 |
readOnly | 设置是否为只读事务 | readOnly=true 只读事务 |
timeout | 设置事务超时时间 | timeout = -1(永不超时) |
rollbackFor | 设置事务回滚异常(class) | rollbackFor = {FileNotFoundException.class} |
rollbackForClassName | 设置事务回滚异常(String) | 同上格式为字符串 |
noRollbackFor | 设置事务不回滚异常(class) | noRollbackFor = {FileNotFoundException.class} |
noRollbackForClassName | 设置事务不回滚异常(String) | 同上格式为字符串 |
propagation | 设置事务传播行为 | …… |
说明:对于RuntimeException类型异常或者Error错误,Spring事务能够进行回滚操作。但是对于非运行时异常,Spring事务是不进行回滚的,所以需要使用rollbackFor来设置要回滚的异常。
3.2 案例:转账业务追加日志
需求和分析
-
需求:实现任意两个账户间转账操作,并对每次转账操作在数据库进行记录
-
需求微缩:A账户减钱,B账户加钱,数据库记录日志
-
分析: ①:基于转账操作案例添加日志模块,实现数据库中记录日志 ②:业务层转账操作(transfer),调用减钱、加钱与记录日志功能
-
实现效果预期: 无论转账操作是否成功,均进行转账操作的日志留痕
-
存在的问题: 日志的记录与转账操作隶属同一个事务,同成功同失败
-
实现效果预期改进: 无论转账操作是否成功,日志必须保留
-
事务传播行为:事务协调员对事务管理员所携带事务的处理态度
【准备工作】环境整备
创建新的LogDao接口
public interface LogDao {@Insert("insert into tbl_log (info,create_date) values(#{info},now())")void log(String info);
}
创建业务接口使用事务
public interface LogService {/*** 记录日志* @param out 转出账户* @param in 转入账户* @param money 金额* 设置事务属性:传播行为设置为需要新事务*/@Transactionalvoid log(String out, String in, Double money);
}
实现类
@Service
public class LogServiceImpl implements LogService {@Autowiredprivate LogDao logDao;public void log(String out, String in, Double money) {logDao.log("转账操作由" + out + "到" + in + ",金额:" + money);}
}
【第一步】在AccountServiceImpl中调用logService中添加日志的方法
因为无论成功与否,都需要记录日志,所以日志放在finally语句块中,但异常不需要捕获,要抛出用来激活事务的处理
/*** 业务接口*/
public interface AccountService {/*** 转账操作* @param out 传出方* @param in 转入方* @param money 金额*/@Transactionalvoid transfer(String out,String in ,Double money) ;
}
@Service
public class AccountServiceImpl implements AccountService {@Autowiredprivate AccountDao accountDao;@Autowiredprivate LogService logService;public void transfer(String out,String in ,Double money) {try{accountDao.outMoney(out,money);//int i = 1/0;accountDao.inMoney(in,money);} finally {logService.log(out,in,money);}}
}
【第二步】在LogService的log()方法上设置事务的传播行为
需求:无论有没有异常日志都要记录下来,不能被回滚
-
先只设置@Transactional,查看运行结果
-
设置成当前操作需要新事务再查看运行结果
public interface LogService {//propagation设置事务属性:传播行为设置为当前操作需要新事务@Transactional(propagation = Propagation.REQUIRES_NEW)void log(String out, String in, Double money);
}
【第三步】运行测试类,查看结果
@RunWith(SpringJUnit4ClassRunner.class) //指定第三方的运行器
@ContextConfiguration(classes = SpringConfig.class) //读取类配置文件
public class AccountServiceTest {@Autowired //自动注入业务对象private AccountService accountService;/*** 转账的测试*/@Testpublic void testTransfer() {accountService.transfer("Jack", "Rose", 10d);}
}
思考:为什么 在LogService的方法上设置propagation = Propagation.REQUIRES_NEW接可以创建新的事务?
这就是事务传播行为(经常会面试提问)
3.3 事务传播行为
传播属性 | Method1 | Method2 |
REQUIRED | 开启TI事务 | 加入T1事务 |
无 | 新建T2事务 | |
REQUIRES_NEW | 开启TI事务 | 新建T2事务 |
无 | 新建T2事务 | |
SUPPORTS | 开启TI事务 | 加入T1事务 |
无 | 无 | |
NOT_SUPPORTED | 开启TI事务 | 无 |
无 | 无 | |
MANDATORY | 开启TI事务 | 加入T1事务 |
无 | ERROR | |
NEVER | 开启TI事务 | ERROR |
无 | 无 | |
NESTED | |
思考:事务会一直生效?有没有事务失效的情况?为什么会失效,大家可以思考一下,这也是一个长问面试题
相关文章:

Spring-4-掌握Spring事务传播机制
今日目标 能够掌握Spring事务配置 Spring事务管理 1 Spring事务简介【重点】 1.1 Spring事务作用 事务作用:在数据层保障一系列的数据库操作同成功同失败 Spring事务作用:在数据层或业务层保障一系列的数据库操作同成功同失败 1.2 案例分析Spring…...

[PyTorch][chapter 49][创建自己的数据集 1]
前言: 后面几章主要利用DataSet 创建自己的数据集,实现建模, 训练,迁移等功能。 目录: pokemon 数据集深度学习工程步骤 一 pokemon 数据集介绍 1.1 pokemon: 数据集地址: 百度网盘路径: https://pan.baidu.com/s/1…...

中间件(二)dubbo负载均衡介绍
一、负载均衡概述 支持轮询、随机、一致性hash和最小活跃数等。 1、轮询 ① sequences:内部的序列计数器 ② 服务器接口方法权重一样:(sequences1)%服务器的数量(决定调用)哪个服务器的服务。 ③ 服务器…...

springboot异步文件上传获取输入流提示找不到文件java.io.FileNotFoundException
springboot上传文件,使用异步操作处理上传的文件数据,出现异常如下: 这个是在异步之后使用传过来的MultipartFile对象尝试调用getInputStream方法发生的异常。 java.io.FileNotFoundException: C:\Users\Administrator\AppData\Local\Temp\to…...

安装jenkins-cli
1、要在 Linux 操作系统上安装 jcli curl -L https://github.com/jenkins-zh/jenkins-cli/releases/latest/download/jcli-linux-amd64.tar.gz|tar xzv sudo mv jcli /usr/local/bin/ 在用户根目录下,增加 jcli 的配置文件: jcli config gen -ifalse …...
linux通过NC工具启动临时端口监听
1.安装nc工具 yum install nc -y2. 启动监听指定端口 #例如监听8080端口 nc -lk 8080#后台监听 nc -lk 8080 &3. 验证 #通过另外一台网络能通的机器,telnet 该机器ip 监听端口能通,并且能接手数据 telnet 192.xxx.xxx.xx 8080...

开源语音聊天软件Mumble
网友 大气 告诉我,Openblocks在国内还有个版本叫 码匠,更贴合国内软件开发的需求,如接入了国内常用的身份认证,接入了国内的数据库和云服务,也对小程序、企微 sdk 等场景做了适配。 在 https://majiang.co/docs/docke…...
JDK 1.6与JDK 1.8的区别
ArrayList使用默认的构造方式实例 jdk1.6默认初始值为10jdk1.8为0,第一次放入值才初始化,属于懒加载 Hashmap底层 jdk1.6与jdk1.8都是数组链表 jdk1.8是链表超过8时,自动转为红黑树 静态方式不同 jdk1.6是先初始化static后执行main方法。 jdk1.8是懒加…...
单片机实训报告
这周我们进行了单片机实训,一周中我们通过七个项目1:P1 口输入/输出 2:继电器控制 3 音频控制 4:子程序设计 5:字符碰头程序设计 6:外部中断 7: 急救车与交通信号灯,练习编写了子程…...

【编织时空四:探究顺序表与链表的数据之旅】
本章重点 链表的分类 带头双向循环链表接口实现 顺序表和链表的区别 缓存利用率参考存储体系结构 以及 局部原理性。 一、链表的分类 实际中链表的结构非常多样,以下情况组合起来就有8种链表结构: 1. 单向或者双向 2. 带头或者不带头 3. 循环或者非…...

PHP8的字符串操作1-PHP8知识详解
字符串是php中最重要的数据之一,字符串的操作在PHP编程占有重要的地位。在使用PHP语言开发web项目的过程中,为了实现某些功能,经常需要对某些字符串进行特殊的处理,比如字符串的格式化、字符串的连接与分割、字符串的比较、查找等…...

电脑提示msvcp140.dll丢失的解决方法,dll组件怎么处理
Windows系统有时在打开游戏或者软件时, 系统会弹窗提示缺少“msvcp140.dll.dll”文件 或者类似错误提示怎么办? 错误背景: msvcp140.dll是Microsoft Visual C Redistributable Package中的一个动态链接库文件,它在运行软件时提…...

stable diffusion基础
整合包下载:秋叶大佬 【AI绘画8月最新】Stable Diffusion整合包v4.2发布! 参照:基础04】目前全网最贴心的Lora基础知识教程! VAE 作用:滤镜微调 VAE下载地址:C站(https://civitai.com/models…...
Greiner–Hormann裁剪算法深度探索:C++实现与应用案例
介绍 在计算几何中,裁剪是一个核心的主题。特别是,多边形裁剪已经被广泛地应用于计算机图形学,地理信息系统和许多其他领域。Greiner-Hormann裁剪算法是其中之一,提供了一个高效的方式来计算两个多边形的交集、并集等。在本文中&…...
Automatically Correcting Large Language Models
本文是大模型相关领域的系列文章,针对《Automatically Correcting Large Language Models: Surveying the landscape of diverse self-correction strategies》的翻译。 自动更正大型语言模型:综述各种自我更正策略的前景 摘要1 引言2 自动反馈校正LLM的…...

【学习FreeRTOS】第8章——FreeRTOS列表和列表项
1.列表和列表项的简介 列表是 FreeRTOS 中的一个数据结构,概念上和链表有点类似,列表被用来跟踪 FreeRTOS中的任务。列表项就是存放在列表中的项目。 列表相当于链表,列表项相当于节点,FreeRTOS 中的列表是一个双向环形链表列表的…...

分布式图数据库 NebulaGraph v3.6.0 正式发布,强化全文索引能力
本次 v3.6.0 版本,主要强化全文索引能力,以及优化部分场景下的 MATCH 性能。 强化 强化增强全文索引功能,具体 pr 参见:#5567、#5575、#5577、#5580、#5584、#5587 优化 支持使用 MATCH 子句检索 VID 或属性索引时使用变量&am…...

在 ubuntu 18.04 上使用源码升级 OpenSSH_7.6p1到 OpenSSH_9.3p1
1、检查系统已安装的当前 SSH 版本 使用命令 ssh -V 查看当前 ssh 版本,输出如下: OpenSSH_7.6p1 Ubuntu-4ubuntu0.7, OpenSSL 1.0.2n 7 Dec 20172、安装依赖,依次执行以下命令 sudo apt update sudo apt install build-essential zlib1g…...

python中可以处理word文档的模块:docx模块
前言 大家早好、午好、晚好吖 ❤ ~欢迎光临本文章 话不多说,直接开搞,如果有什么疑惑/资料需要的可以点击文章末尾名片领取源码 一.docx模块 Python可以利用python-docx模块处理word文档,处理方式是面向对象的。 也就是说python-docx模块…...

TikTok或将于8月底关闭半闭环、速卖通或将推出“半托管”模式
《出海周报》是运营坛为外贸企业主和外贸人独家打造的重要资讯栏目,聚焦企业出海、海外市场动态、海外监管政策等方面,以简捷的方式,提升读者获取资讯的效率。 接下来运营坛为大家带来第15期出海周报,快来看看这周国内外市场发生了…...

19c补丁后oracle属主变化,导致不能识别磁盘组
补丁后服务器重启,数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后,存在与用户组权限相关的问题。具体表现为,Oracle 实例的运行用户(oracle)和集…...
ubuntu搭建nfs服务centos挂载访问
在Ubuntu上设置NFS服务器 在Ubuntu上,你可以使用apt包管理器来安装NFS服务器。打开终端并运行: sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享,例如/shared: sudo mkdir /shared sud…...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动
一、前言说明 在2011版本的gb28181协议中,拉取视频流只要求udp方式,从2016开始要求新增支持tcp被动和tcp主动两种方式,udp理论上会丢包的,所以实际使用过程可能会出现画面花屏的情况,而tcp肯定不丢包,起码…...
《Playwright:微软的自动化测试工具详解》
Playwright 简介:声明内容来自网络,将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具,支持 Chrome、Firefox、Safari 等主流浏览器,提供多语言 API(Python、JavaScript、Java、.NET)。它的特点包括&a…...
MVC 数据库
MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...

对WWDC 2025 Keynote 内容的预测
借助我们以往对苹果公司发展路径的深入研究经验,以及大语言模型的分析能力,我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际,我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测,聊作存档。等到明…...

C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...
【HTML-16】深入理解HTML中的块元素与行内元素
HTML元素根据其显示特性可以分为两大类:块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...
【python异步多线程】异步多线程爬虫代码示例
claude生成的python多线程、异步代码示例,模拟20个网页的爬取,每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程:允许程序同时执行多个任务,提高IO密集型任务(如网络请求)的效率…...
今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存
文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...