工作中遇到的一次springboot异步注解@Async问题
前言:这是一次工作中遇见的问题,项目用的是springboot+vue的前后端分离项目,当时想要在前端调用后台的接口实现异步调用生成文件方法,可是在标记过@Async注解后发现并没有实现想要的异步调用这个方法。
解决过程:(犹豫不决查百度,作为一个初级程序员有问题查百度就对了。)
可能的情况(仅是解决办法,原理及个人分析在后面,如有不对欢迎指出,万分感谢!!)
- 我的项目组长给我提了个建议,让我每一行都打印一个时间戳,让我看看是哪一行代码花费的时间比较多。我没有打印时间戳,而是进行了日志打印。后发现就是异步未生效。
- 我发现springboot中再调用@Async注解时,前置条件就是要在项目的启动类中标记@EnableAsync来保证实现项目中的@Async注解可以生效。这是异步注解使用的前置条件,但是显然我的情况和他不同。
- 然后我在百度上发现了一篇文章(点此跳转链接,这篇文章写的很详细),有一种情况会导致@Async注解的失效,那就是被调用的异步方法和调用异步方法的方法在同一个类中,就会出现异步方法失效的情况。
**解决:**最后我将调用异步的方法抽离出来,放在一个新的类中通过调用这个类就实现了异步功能。
注意事项(搬运)
如下方式会使@Async失效
- 异步方法使用static修饰
- 异步类没有使用@Component注解(或其他注解)导致spring无法扫描到异步类
- 异步方法不能与异步方法在同一个类中
- 类中需要使用@Autowired或@Resource等注解自动注入,不能自己手动new对象
- 如果使用SpringBoot框架必须在启动类中增加@EnableAsync注解
- 在Async 方法上标注@Transactional是没用的。 在Async 方法调用的方法上标注@Transactional 有效。
(例如: 方法A,使用了@Async/@Transactional来标注,但是无法产生事务控制的目的。
方法B,使用了@Async来标注, B中调用了C、D,C/D分别使用@Transactional做了标注,则可实现事务控制的目的。)
原文链接:https://blog.csdn.net/belongtocode/article/details/103996923
个人分析
-
关于@EnableAsync
这个注解是用于表示在springboot的启动类中其作用是用来表示开启异步功能
springboot中有很多类似注解,格式均为@Enable + 相关功能。 只有在开启这类注解时才能在项目中使用这些功能。 -
@EnableAsync 与 @Async (个人理解,后续可能更新)
其中@EnableAsync用于在项目中开启线程池,springboot在项目开启时扫描所有的相关类并生成相应的动态代理的类,而有@Async注解后则是从线程池中拿取一个线程并通过动态代理的方式调用这个方法。这也是为什么调用和被调用的异步方法在同一个类中时,将会直接调用这个异步方法,所以这个异步方法就没有实现。