news 2026/7/2 6:00:12

异步方法调用详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
异步方法调用详解

文档说明

本文主要针对同类,不同类方法之间的异步调用详解。

本文基于Spring @Async 异步调用四种场景教学文档。

1.所有入口方法 testMain() 均添加 @Transactional 事务;
2.区分:异步逻辑是否和主方法同一事务、是否跟随主方法回滚;
3.核心前置知识点:@Async 基于 AOP 代理生效,同类this调用失效;afterCommit 事务提交后才执行回调逻辑;
4.前置配置:启动类添加 @EnableAsync 开启异步支持。

场景一:A 类 testMain 事务内,异步调用外部 B 类 testB1

1. 主业务类 ClassA

import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; @Service public class ClassA { @Resource private ClassB classB; /** * 主入口方法,开启事务 */ @Transactional public void testMain() { // 1. 主线务数据库操作(和testMain同事务) // 2. 异步调用外部B类方法 classB.testB1(); // 3. 其余业务操作 // 主线程仅将异步任务提交线程池,无需阻塞等待异步逻辑执行完毕,继续向下执行业务代码。 } }

2.外部异步类 ClassB

import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; @Service public class ClassB { /** * 异步业务方法 * 独立线程、独立事务 */ @Async @Transactional public void testB1() { // 数据库操作、耗时业务逻辑 } }

3.事务回滚说明

若testMain中的业务于第一步的代码发生异常回滚,testB1不会随testMain一起回滚,testB1没执行。

若testMain中的业务于第三步的代码发生了异常回滚,则testB1已经执行了。

testB1 内部报错:testMain事务不受影响,testMain数据正常提交。因为@Async相当于开启了一个全新的线程,两个之间互不影响。

场景二、A 类 testMain 事务内,afterCommit 回调中异步调用外部 B 类 testB1

1. 主业务类 ClassA

import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.support.TransactionSynchronization; import org.springframework.transaction.support.TransactionSynchronizationManager; import javax.annotation.Resource; @Service public class ClassA { @Resource private ClassB classB; @Transactional public void testMain() { // 主线务数据库操作 // 注册事务提交后回调 TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { @Override public void afterCommit() { // 主线事务完全提交落库后,才异步执行 classB.testB1(); } }); } }

2.外部异步类 ClassB

import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; @Service public class ClassB { /** * 异步业务方法 * 独立线程、独立事务 */ @Async @Transactional public void testB1() { // 数据库操作、耗时业务逻辑 } }

3.事务回滚说明

若testMain中的业务代码发生异常回滚,testB1压根不会执行,因为afterCommit 回调仅在主线事务完整提交成功后才执行;主线事务回滚时,回调逻辑完全不执行。

testB1 内部报错:testMain事务不受影响,testMain数据正常提交。

场景三、A 类 testMain 事务内,异步调用本类 3 个方法

每次 getBean 获取代理调用本类方法,直接用this调用会使异步注解失效。

针对多个异步本类方法的调用,建议不用获取getBean的方式调用,频繁通过 getBean 获取代理对象存在重复容器查询开销,多异步方法时不利于统一管控线程池参数。建议使用线程池管理调用。

1. 主业务类ClassA

import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @Service public class ClassA implements ApplicationContextAware { private ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } @Transactional public void testMain() { // 1.主线务数据库操作 // 2.每次通过容器获取代理对象,调用本类异步方法 ClassA proxy = applicationContext.getBean(ClassA.class); proxy.testSub1(); proxy.testSub2(); proxy.testSub3(); // 3.其余业务操作 } @Async @Transactional public void testSub1() { // 异步业务1 } @Async @Transactional public void testSub2() { // 异步业务2 } @Async @Transactional public void testSub3() { // 异步业务3 } }

2. 事务回滚说明

若testMain中的业务于第一步的代码发生异常回滚,testSub不会随testMain一起回滚,testSub没执行。

若testMain中的业务于第三步的代码发生了异常回滚,testSub已经执行了。

testB1 内部报错:testMain事务不受影响,testMain数据正常提交。因为@Async相当于开启了一个全新的线程,两个之间互不影响。

场景四、A 类 testMain 事务内,afterCommit 回调中异步调用本类 3 个方法

1. 主业务类ClassA

import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.support.TransactionSynchronization; import org.springframework.transaction.support.TransactionSynchronizationManager; @Service public class ClassA implements ApplicationContextAware { private ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } @Transactional public void testMain() { // 主线务数据库操作 TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { @Override public void afterCommit() { // 事务提交后,获取代理执行本类异步方法 ClassA proxy = applicationContext.getBean(ClassA.class); proxy.testSub1(); proxy.testSub2(); proxy.testSub3(); } }); } @Async @Transactional public void testSub1() {} @Async @Transactional public void testSub2() {} @Async @Transactional public void testSub3() {} }

2. 事务回滚说明

若testMain中的业务代码发生异常回滚,testSub压根不会执行,因为afterCommit 回调仅在主线事务完整提交成功后才执行;主线事务回滚时,回调逻辑完全不执行。

testSub 内部报错:testMain事务不受影响,testMain数据正常提交。

总结说明

场景执行时机主线回滚后异步是否执行异步报错是否回滚主线
场景 1 直接异步调用外部类主线执行中并行触发可能执行不回滚主线
场景 2 afterCommit 异步外部类主线事务提交后触发不会执行不回滚主线
场景 3 直接异步调用本类 (getBean)主线执行中并行触发可能执行不回滚主线
场景 4 afterCommit 异步调用本类 (getBean)主线事务提交后触发不会执行不回滚主线

使用建议

1.若有数据库操作一类的建议使用场景2

2.针对多个异步本类方法的调用,建议不用获取getBean的方式调用,频繁通过 getBean 获取代理对象存在重复容器查询开销,多异步方法时不利于统一管控线程池参数。建议使用线程池管理调用。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/2 5:59:06

零食生产线爬坡转弯输送系统(双爬坡机+转弯机)选型指南

零食生产线爬坡转弯输送系统选型指南:双爬坡机90度转弯机组合式草纹格挡皮带流水线技术解析 一、零食生产线的空间挑战与输送组合方案 休闲零食行业具有品种多、批次频、换线快的特点,生产线布局常面临空间受限、工序分散、高度落差大等挑战。单一方向的…

作者头像 李华
网站建设 2026/7/2 5:57:36

透明质酸敷料批发商实力之选:四川昂宇医疗器械有限公司深度解析

在透明质酸敷料领域,专业批发商的选择直接关系到产品品质与客户体验。四川昂宇医疗器械有限公司凭借深耕行业的积累与全链条服务能力,成为众多医疗机构与美容机构值得关注的合作伙伴。公司以“精准适配、合规交付”为核心,在供应链整合、方案…

作者头像 李华
网站建设 2026/7/2 5:57:22

WinBtrfs完全指南:在Windows系统上无缝访问Linux Btrfs文件系统

WinBtrfs完全指南:在Windows系统上无缝访问Linux Btrfs文件系统 【免费下载链接】btrfs WinBtrfs - an open-source btrfs driver for Windows 项目地址: https://gitcode.com/gh_mirrors/bt/btrfs 还在为Windows无法读取Linux Btrfs分区而烦恼吗&#xff1f…

作者头像 李华
网站建设 2026/7/2 5:56:24

九年深耕亚克力,以匠心方寸,承载世界赛事的荣光

在东莞的制造业沃土上,藏着很多不张扬、却有真本事的中小型工厂,东莞市吉昌亚克力制品有限公司便是其中之一。自2017年成立至今,九年时光沉淀,45人的精干团队、2750平米的标准化厂房、年均2500万的稳定产能,没有夸张的…

作者头像 李华
网站建设 2026/7/2 5:56:16

【安全月报】| 6 月加密货币领域因安全事件损失约 8173 万美元

零时科技每月安全事件看点开始了!据多家区块链安全监测平台统计,2026 年 6 月加密货币领域安全态势呈现“攻击频率创年内新高,钓鱼攻击占比显著上升”的特点。当月因安全事件造成的总损失约 8173 万美元,其中黑客攻击与合约漏洞相…

作者头像 李华
网站建设 2026/7/2 5:54:30

深度学习图像数据集构建:从采集到标注的工程化实践

1. 项目概述:为什么你手里的“图片”根本不能直接喂给模型做深度学习项目时,我见过太多人卡在第一步——数据。不是模型调不好,不是代码写不对,而是手里那堆标着“猫狗数据集”“工业缺陷图”的文件夹,点开一看全是模糊…

作者头像 李华