深入了解Spring Boot中@Async注解的8大坑点
文章目录
- 1. 缺少@EnableAsync注解
- 2. 异步方法需独立
- 3. 不同的异步方法间无法相互调用
- 4. 返回值为void的异步方法无法捕获异常
- 5. 外部无法直接调用带有@Async注解的方法
- 6. @Async方法不适用于private方法
- 7. 缺失异步线程池配置
- 8. 异步方法与事务的兼容
- 结语

🎉深入了解Spring Boot中@Async注解的8大坑点
- ☆* o(≧▽≦)o *☆嗨~我是IT·陈寒🍹
- ✨博客主页:IT·陈寒的博客
- 🎈该系列文章专栏:架构设计
- 📜其他专栏:Java学习路线 Java面试技巧 Java实战项目 AIGC人工智能 数据结构学习
- 🍹文章作者技术和水平有限,如果文中出现错误,希望大家能指正🙏
- 📜 欢迎大家关注! ❤️
Spring Boot是一个流行的Java开发框架,提供了丰富的功能和便捷的配置,使得开发者可以更专注于业务逻辑。在异步编程方面,Spring Boot提供了@Async
注解,它能够让方法异步执行,提高系统的并发性能。然而,在使用@Async
注解时,有一些潜在的坑需要注意。本文将深入探讨Spring Boot中使用@Async
注解时可能遇到的8大坑点,并提供相应的解决方案。
1. 缺少@EnableAsync注解
在使用@Async
注解之前,必须在Spring Boot应用程序的主配置类上添加@EnableAsync
注解,以启用异步方法的支持。如果忽略了这一步,@Async
注解将不会生效。
@SpringBootApplication
@EnableAsync
public class YourApplication {public static void main(String[] args) {SpringApplication.run(YourApplication.class, args);}
}
2. 异步方法需独立
被@Async
注解修饰的方法不能直接被同一个类中的其他方法调用。因为Spring会在运行时生成一个代理类,调用异步方法时实际上是调用这个代理类的方法。因此,如果在同一个类中直接调用异步方法,@Async
注解将不会生效。
@Service
public class YourService {@Asyncpublic void asyncMethod() {// 异步执行的逻辑}public void callingAsyncMethod() {// 直接调用asyncMethod将无法异步执行asyncMethod();}
}
解决方案是通过注入YourService
的代理对象来调用异步方法。
@Service
public class YourService {@Autowiredprivate YourService self;@Asyncpublic void asyncMethod() {// 异步执行的逻辑}public void callingAsyncMethod() {// 通过代理对象调用异步方法self.asyncMethod();}
}
3. 不同的异步方法间无法相互调用
在同一个类中,一个异步方法调用另一个异步方法,也会出现不会异步执行的问题。这是由于Spring默认使用基于代理的AOP来实现异步方法,代理对象内部的方法调用不会触发AOP拦截。
@Service
public class YourService {@Asyncpublic void asyncMethod1() {// 异步执行的逻辑}@Asyncpublic void asyncMethod2() {// 异步执行的逻辑asyncMethod1(); // 这里调用将不会异步执行}
}
解决方案是通过AopContext.currentProxy()获取当前代理对象,再调用异步方法。
@Service
public class YourService {@Autowiredprivate YourService self;@Asyncpublic void asyncMethod1() {// 异步执行的逻辑}@Asyncpublic void asyncMethod2() {// 异步执行的逻辑self.asyncMethod1(); // 通过代理对象调用将异步执行}
}
4. 返回值为void的异步方法无法捕获异常
如果使用@Async
注解的异步方法的返回值为void
,那么这个方法中抛出的异常将无法被捕获。这是因为在异步方法的调用线程和实际执行异步方法的线程之间无法传递异常。
@Service
public class YourService {@Asyncpublic void asyncMethod() {// 异步执行的逻辑throw new RuntimeException("Async method exception");}
}
解决方案是将返回值设置为Future
,这样就可以在调用get()
方法时捕获到异常。
@Service
public class YourService {@Asyncpublic Future<Void> asyncMethod() {// 异步执行的逻辑throw new RuntimeException("Async method exception");}
}
在调用异步方法时,可以通过Future
的get()
方法捕获到异常。
@Service
public class YourService {@Autowiredprivate YourService self;public void callAsyncMethod() {try {self.asyncMethod().get();} catch (Exception e) {// 捕获异常}}
}
5. 外部无法直接调用带有@Async注解的方法
如果在同一个类中直接调用带有@Async
注解的方法,是无法异步执行的。因为Spring会在运行时生成一个代理类,外部直接调用实际上是调用的原始类的方法,而不是代理类的方法。
@Service
public class YourService {@Asyncpublic void asyncMethod() {// 异步执行的逻辑}
}@Service
public class AnotherService {@Autowiredprivate YourService yourService;public void callAsyncMethod() {// 外部直接调用asyncMethod将无法异步执行yourService.asyncMethod();}
}
解决方案是通过注入YourService
的代理对象来调用异步方法。
@Service
public class YourService {@Autowiredprivate YourService self;@Asyncpublic void asyncMethod() {// 异步执行的逻辑}
}@Service
public class AnotherService {@Autowiredprivate YourService self;public void callAsyncMethod() {// 通过代理对象调用异步方法self.asyncMethod();}
}
6. @Async方法不适用于private方法
@Async
注解只对公有方法有效,因此`private
方法无法异步执行。如果尝试给一个
private方法添加
@Async`注解,将不会产生任何效果。
@Service
public class YourService {@Asyncprivate void asyncMethod() {// 这里的@Async注解将不会生效}
}
解决方案是将要异步执行的逻辑抽取到一个公有方法中,并在私有方法中调用这个公有方法。
@Service
public class YourService {@Asyncpublic void asyncMethod() {doAsyncMethod();}private void doAsyncMethod() {// 异步执行的逻辑}
}
7. 缺失异步线程池配置
在使用@Async
注解时,Spring Boot默认会创建一个线程池来执行异步方法。如果没有进行配置,默认使用的是SimpleAsyncTaskExecutor
,这是一个单线程的执行器,可能会导致性能瓶颈。
为了解决这个问题,可以配置一个合适的线程池。以下是一个示例的配置:
@Configuration
@EnableAsync
public class AsyncConfig extends AsyncConfigurerSupport {@Overridepublic Executor getAsyncExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(5);executor.setMaxPoolSize(10);executor.setQueueCapacity(25);executor.setThreadNamePrefix("Async-");executor.initialize();return executor;}
}
这个配置使用了ThreadPoolTaskExecutor
,并设置了核心线程数、最大线程数、队列容量等参数,根据实际情况进行调整。
8. 异步方法与事务的兼容
在默认情况下,使用@Async
注解的方法与事务是不兼容的。因为在使用事务的方法中调用使用@Async
注解的方法时,事务将无法传播到异步方法中,异步方法将在没有事务的情况下执行。
解决方案是将@Async
注解添加到另外一个类的方法上,通过代理对象来调用异步方法。
@Service
public class YourService {@Autowiredprivate AsyncService asyncService;@Transactionalpublic void transactionalMethod() {// 在事务中调用异步方法asyncService.asyncMethod();}
}@Service
public class AsyncService {@Asyncpublic void asyncMethod() {// 异步执行的逻辑}
}
通过将异步方法移动到另一个类中,可以确保异步方法在新的事务中执行,与外部事务不会产生冲突。
结语
使用@Async
注解能够提高系统的并发性能,但在使用时需要注意一些潜在的问题。通过深入了解Spring Boot中@Async
注解的这8大坑点,并采取相应的解决方案,可以更好地应用异步编程,确保系统的可靠性和性能。希望本文对您理解和使用Spring Boot中的异步注解有所帮助。
🧸结尾 ❤️ 感谢您的支持和鼓励! 😊🙏
📜您可能感兴趣的内容:
- 【Java面试技巧】Java面试八股文 - 掌握面试必备知识(目录篇)
- 【Java学习路线】2023年完整版Java学习路线图
- 【AIGC人工智能】Chat GPT是什么,初学者怎么使用Chat GPT,需要注意些什么
- 【Java实战项目】SpringBoot+SSM实战:打造高效便捷的企业级Java外卖订购系统
- 【数据结构学习】从零起步:学习数据结构的完整路径
相关文章:

深入了解Spring Boot中@Async注解的8大坑点
文章目录 1. 缺少EnableAsync注解2. 异步方法需独立3. 不同的异步方法间无法相互调用4. 返回值为void的异步方法无法捕获异常5. 外部无法直接调用带有Async注解的方法6. Async方法不适用于private方法7. 缺失异步线程池配置8. 异步方法与事务的兼容结语 🎉深入了解S…...

C语言——深入理解指针(3)
目录 1. 字符指针 2. 数组指针 2.1 数组指针变量 2.2 数组指针变量的初始化 3.二维数组传参(本质) 4. 函数指针 4.1 函数指针变量的创建 4.2 函数指针的使用 4.3 typedef 5. 函数指针数组 6. 转移表(函数指针数组的使用ÿ…...

图书管理系统源码,图书管理系统开发,图书借阅系统源码配置和运行图解源码已附加
目录 配置简介和软件条件 数据库附件配置 vs应用程序web.config配置数据库链接字符串 数据库文件脚本代码 配置简介和软件条件 所需要的软件是Vs2017以上数据库是Sqlserver2012以上,如果数据库附件不了可以使用数据库脚本附件数据库脚本会在文章末尾写出来。可以…...

FFmpeg介绍
官方网站:http://www.ffmpeg.org/ 项目组成 libavformat 封装模块,封装了Protocol层和Demuxer、Muxer层,使得协议和格式对于开发者来说是透明的。FFmpeg能否支持一种封装格式的视频的封装与解封装,完全取决于这个库,…...
修改网卡PHY的灯-RK3568
文章目录 前言1.定制PHY的灯2.通过命令修改LED状态3.修改驱动效果前言 前面我们已经移植了网卡到开发板上面,也能够正常的进行通信,但是,我们会发现座子上面的灯并没有全部亮起来,而且这些灯的含义是什么,并没有讲解到,这里,就此问题,展开学习。 PHY 有一个重要的功能…...

11月29日作业
作业: 自己封装一个矩形类(Rect),拥有私有属性:宽度(width)、高度(height), 定义公有成员函数: 初始化函数:void init(int w, int h) 更改宽度的函数:set_w(int w) 更改高度的函数:set_h(int h) 输出该矩形的周长和面积函数:void show(…...

【从删库到跑路 | MySQL总结篇】表的增删查改(进阶下)
个人主页:兜里有颗棉花糖 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 兜里有颗棉花糖 原创 收录于专栏【MySQL学习专栏】🎈 本专栏旨在分享学习MySQL的一点学习心得,欢迎大家在评论区讨论💌 目录 一、联合…...

【机器学习 | 可视化系列】可视化系列 之 决策树可视化
🤵♂️ 个人主页: AI_magician 📡主页地址: 作者简介:CSDN内容合伙人,全栈领域优质创作者。 👨💻景愿:旨在于能和更多的热爱计算机的伙伴一起成长!!&…...
配置阿里云的yum仓库
目录 配置阿里云的yum源 清理官方yum源 下载阿里云的yum源 centos7下载阿里云yum源: 清理yum缓存:yum cleam all 生成自己的yum缓存:yum makecache 使用centos自带的官方yum源下载很慢,那今天来跟大家说说配置阿里云的yum仓…...
Kubernetes之kubeadm日志展示篇—K8S私有云worker节点gluster安装部署
文章目录 一. 服务器信息1.1 环境准备1.2 配置hosts解析记录 二. 安装与部署2.1 配置仓库 (所有节点)2.2 安装服务 (所有节点)2.3 启动服务 (所有节点)2.4 配置资源池 (主节点)2.5 创…...

P3368 【模板】树状数组 2 (区间修改,单点查询)
本题链接:【模板】树状数组 2 - 洛谷 题目: 输入 5 5 1 5 4 2 3 1 2 4 2 2 3 1 1 5 -1 1 3 5 7 2 4 输出 6 10 思路: 根据题意,这里是需要区间添加值,单点查询值。如果区间添加值中暴力去一个个加值,肯定…...

智慧城市运营管理平台解决方案:PPT全文61页,附下载
关键词:智慧城市建设方案,智慧城市解决方案,智慧城市的发展前景和趋势,智慧城市建设内容,智慧城市运营管理平台 一、智慧城市运营平台建设背景 随着城市化进程的加速,城市面临着诸多挑战,如环…...

Vue性能优化方法
一、前言 1.1 为什么需要性能优化 用户体验:优化性能可以提升用户体验,降低加载时间和响应时间,让用户更快地看到页面内容。SEO优化:搜索引擎更喜欢快速响应的网站,优化性能可以提高网站的排名。节约成本࿱…...

关于网站的favicon.ico图标的设置需要注意的几点
01-必须在网页的head标签中放上对icon图标的说明语句: 比如下面这样的语句: <link rel"shortcut icon" href"/favicon.ico">否则,浏览器虽然能读到图标,但是不会把图标显示在标签上。 02-为了和本地开…...

PHP中关于func_get_args()方法
首先呢这个函数出现的是比较早的,大致应该是PHP4出现的, func_get_args — 返回一个包含函数参数列表的数组 说明 func_get_args(): array 获取函数参数列表的数组。 该函数可以配合 func_get_arg() 和 func_num_args() 一起使用,从而使得用户自定义函数可以接…...

EMA训练微调
就是取前几个epoch的weight的平均值,可以缓解微调时的灾难性遗忘(因为新数据引导,模型权重逐渐,偏离训练时学到的数据分布,忘记之前学好的先验知识) class EMA():def __init__(self, model, decay):self.…...
Kafka集群部署详细教程
版本说明 Ubuntu 18.04.6Zookeeper 3.5.9Kafka 2.7.0JDK8 集群配置 操作系统ip域名Zookeeper 端口Kafka 端口Ubuntu 18.04.6192.168.50.131kafka1.com21819092Ubuntu 18.04.6192.168.50.132kafka2.com21819092Ubuntu 18.04.6192.168.50.133kafka3.com21819092 安装 vim, cu…...

交叉编译
1. 交叉开发 交叉编译: 在电脑把程序编写 编译 调试好 再下载到嵌入式产品中运行 编译: gcc 之前编译环境和运行环境是一样的 交叉编译: 编译 把编译代码和运行分开 编译代码在虚拟机中 运行…...
数据结构与算法之递归: LeetCode 46. 全排列 (Typescript版)
全排列 https://leetcode.cn/problems/permutations/ 描述 给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。 示例 1 输入:nums [1,2,3] 输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,…...
SQL中 JOIN 的两种连接类型:内连接(自然连接、自连接、交叉连接)、外连接(左外连接、右外连接、全外连接)
SQL中 JOIN 的两种连接类型:内连接(自然连接、自连接、交叉连接)、外连接(左外连接、右外连接、全外连接) 1. 自然连接(natural join)(内连接) 学生表 mysql> sele…...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具
作者:来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗?了解下一期 Elasticsearch Engineer 培训的时间吧! Elasticsearch 拥有众多新功能,助你为自己…...

定时器任务——若依源码分析
分析util包下面的工具类schedule utils: ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类,封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz,先构建任务的 JobD…...

高等数学(下)题型笔记(八)空间解析几何与向量代数
目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...

《基于Apache Flink的流处理》笔记
思维导图 1-3 章 4-7章 8-11 章 参考资料 源码: https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...

让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比
在机器学习的回归分析中,损失函数的选择对模型性能具有决定性影响。均方误差(MSE)作为经典的损失函数,在处理干净数据时表现优异,但在面对包含异常值的噪声数据时,其对大误差的二次惩罚机制往往导致模型参数…...
音视频——I2S 协议详解
I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议,专门用于在数字音频设备之间传输数字音频数据。它由飞利浦(Philips)公司开发,以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...

AI语音助手的Python实现
引言 语音助手(如小爱同学、Siri)通过语音识别、自然语言处理(NLP)和语音合成技术,为用户提供直观、高效的交互体验。随着人工智能的普及,Python开发者可以利用开源库和AI模型,快速构建自定义语音助手。本文由浅入深,详细介绍如何使用Python开发AI语音助手,涵盖基础功…...

C++_哈希表
本篇文章是对C学习的哈希表部分的学习分享 相信一定会对你有所帮助~ 那咱们废话不多说,直接开始吧! 一、基础概念 1. 哈希核心思想: 哈希函数的作用:通过此函数建立一个Key与存储位置之间的映射关系。理想目标:实现…...

Linux 下 DMA 内存映射浅析
序 系统 I/O 设备驱动程序通常调用其特定子系统的接口为 DMA 分配内存,但最终会调到 DMA 子系统的dma_alloc_coherent()/dma_alloc_attrs() 等接口。 关于 dma_alloc_coherent 接口详细的代码讲解、调用流程,可以参考这篇文章,我觉得写的非常…...

SQL注入篇-sqlmap的配置和使用
在之前的皮卡丘靶场第五期SQL注入的内容中我们谈到了sqlmap,但是由于很多朋友看不了解命令行格式,所以是纯手动获取数据库信息的 接下来我们就用sqlmap来进行皮卡丘靶场的sql注入学习,链接:https://wwhc.lanzoue.com/ifJY32ybh6vc…...