@aspect注解_Spring中异步注解@Async的使用、原理及使用时可能导致的问题

本文深入剖析Spring中的@Async注解,介绍其基本使用方法,探讨代理原理、切点逻辑和异步实现机制。同时,文章分析了@Async可能导致的循环依赖错误和默认线程池不复用线程问题,并提供了相应的解决方案。
摘要由CSDN通过智能技术生成

前言

最近,很多同学碰到了下面这个问题,添加了Spring提供的一个异步注解@Async循环依赖无法被解决了,下面是一些读者的留言跟群里同学碰到的问题:

cddb6e9eedfce9c4eb3941d83fc8ce64.png
cfa8928948c1a4f4089ebc5af2581bfa.png

本着讲一个知识点就要讲明白、讲透彻的原则,我决定单独写一篇这样的文章对@Async这个注解做一下详细的介绍,这个注解带来的问题远远不止循环依赖这么简单,如果对它不够熟悉的话建议慎用。

  

文章要点

d64e3172d1fd6e52e8b8a06547c920a6.png

  

@Async的基本使用

这个注解的作用在于可以让被标注的方法异步执行,但是有两个前提条件 1. 配置类上添加@EnableAsync注解 2. 需要异步执行的方法的所在类由Spring管理 3. 需要异步执行的方法上添加了@Async注解 我们通过一个Demo体会下这个注解的作用吧 第一步,配置类上开启异步:
@EnableAsync@Configuration@ComponentScan("com.dmz.spring.async")public class Config {
    
}
第二步,
@Component  // 这个类本身要被Spring管理public class DmzAsyncService {
    @Async  // 添加注解表示这个方法要异步执行public void testAsync(){
    try {
    
   TimeUnit.SECONDS.sleep(1);
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
  System.out.println("testAsync invoked");
 }
}
第三步,测试异步执行
public class Main {
    public static void main(String[] args) {
    
  AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(Config.class);
  DmzAsyncService bean = ac.getBean(DmzAsyncService.class);
  bean.testAsync();
  System.out.println("main函数执行完成");
 }
}// 程序执行结果如下:// main函数执行完成// testAsync invoked
通过上面的例子我们可以发现, DmzAsyncService 中的 testAsync 方法是异步执行的,那么这背后的原理是什么呢?我们接着分析

 

原理分析

我们在分析某一个技术的时候,最重要的事情是,一定一定要找到代码的入口,像Spring这种都很明显,入口必定是在 @EnableAsync 这个注解上面,我们来看看这个注解干了啥事(本文基于 5.2.x 版本)
@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented// 这里是重点,导入了一个ImportSelector@Import(AsyncConfigurationSelector.class)public @interface EnableAsync {
    // 这个配置可以让程序员配置需要被检查的注解,默认情况下检查的就是@Async注解
 Class extends Annotation> annotation() default Annotation.class;// 默认使用jdk代理boolean proxyTargetClass() default false;// 默认使用Spring AOPAdviceMode mode() default AdviceMode.PROXY;// 在后续分析我们会发现,这个注解实际往容器中添加了一个// AsyncAnnotationBeanPostProcessor,这个后置处理器实现了Ordered接口// 这个配置主要代表了AsyncAnnotationBeanPostProcessor执行的顺序int order() default Ordered.LOWEST_PRECEDENCE;
}
上面这个注解做的最重要的事情就是导入了一个 AsyncConfigurationSelector ,这个类的源码如下:
public class AsyncConfigurationSelector extends AdviceModeImportSelector<EnableAsync> {
    private static final String ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME ="org.springframework.scheduling.aspectj.AspectJAsyncConfiguration";@Override@Nullablepublic String[] selectImports(AdviceMode adviceMode) {
    switch (adviceMode) {
    // 默认会使用SpringAOP进行代理case PROXY:return new String[] {ProxyAsyncCo
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值