当前位置: 首页 > news >正文

深入了解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");}
}

在调用异步方法时,可以通过Futureget()方法捕获到异常。

@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外卖订购系统
  • 【数据结构学习】从零起步:学习数据结构的完整路径

在这里插入图片描述

http://www.lryc.cn/news/248264.html

相关文章:

  • C语言——深入理解指针(3)
  • 图书管理系统源码,图书管理系统开发,图书借阅系统源码配置和运行图解源码已附加
  • FFmpeg介绍
  • 修改网卡PHY的灯-RK3568
  • 11月29日作业
  • 【从删库到跑路 | MySQL总结篇】表的增删查改(进阶下)
  • 【机器学习 | 可视化系列】可视化系列 之 决策树可视化
  • 配置阿里云的yum仓库
  • Kubernetes之kubeadm日志展示篇—K8S私有云worker节点gluster安装部署
  • P3368 【模板】树状数组 2 (区间修改,单点查询)
  • 智慧城市运营管理平台解决方案:PPT全文61页,附下载
  • Vue性能优化方法
  • 关于网站的favicon.ico图标的设置需要注意的几点
  • PHP中关于func_get_args()方法
  • EMA训练微调
  • Kafka集群部署详细教程
  • 交叉编译
  • 数据结构与算法之递归: LeetCode 46. 全排列 (Typescript版)
  • SQL中 JOIN 的两种连接类型:内连接(自然连接、自连接、交叉连接)、外连接(左外连接、右外连接、全外连接)
  • 微信小程序记住密码,让登录解放双手
  • 国内划片机行业四大企业之博捷芯:技术驱动,领跑未来
  • 后端整合Swagger+Knife4j接口文档
  • k8s中批量处理Pod应用的Job和CronJob控制器介绍
  • UE5 范围内随机生成
  • 杂记 | 使用Docker安装并配置MongoDB以支持事务(单副本,并解决了证书文件错误的问题)
  • css三角,鼠标样式,溢出文字
  • 远程桌面访问MATLAB 2018B,提示License Manger Error -103,终极解决方案
  • Jmeter基础和概念
  • 【Linux 带宽限速】trickle,限制docker 上传速度
  • MindStudio学习记录三:推理应用开发 acl mindx sdk