spring boot项目使用@Async注解的坑

关于spring boot项目使用@Async注解的坑,有以下几个注意点:

一、@EnableAsync开启异步支持

首先需要在启动类上加上@EnableAsync注解,开启异步支持。示例代码如下:

@SpringBootApplication
@EnableAsync
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class);
    }
}

二、@Async使用时需要注意的问题

使用@Async注解时需要注意以下几个问题:

1. 修饰方法必须是public

被@Async注解修饰的方法必须是public,否则会抛出异常。示例代码如下:

@Service
public class AsyncService {

    @Async
    private void asyncMethod() {
        // ...
    }
}

会抛出以下异常:

org.springframework.aop.framework.AopInvocationException: 
  Null return value from advice does not match primitive return type for:
  public void com.example.demo.service.AsyncService.asyncMethod()
  with params [] of [null]

将private改成public即可:

@Service
public class AsyncService {

    @Async
    public void asyncMethod() {
        // ...
    }
}

2. 异步方法不能和同步方法混淆

如果在同一个类中同时存在同步和异步方法,那么异步方法必须标注@Async,否则会导致同步方法变为异步方法。示例代码如下:

@Service
public class AsyncService {

    public void syncMethod() {
        // ...
    }

    @Async
    public void asyncMethod() {
        // ...
    }
}

此时,如果调用syncMethod方法,就会变成异步方法,因为同一个类中已经存在异步方法了。要解决这个问题,只需将syncMethod标注为@Async(false)即可。示例代码如下:

@Service
public class AsyncService {

    public void syncMethod() {
        // ...
    }

    @Async
    public void asyncMethod() {
        // ...
    }
}

三、示例代码

1. 注入方式问题

@Service
public class AsyncService {
    public void syncMethod() {
        // ...
    }

    @Async
    public void asyncMethod() {
        // ...
    }
}

@Component
public class MyClass {
    @Autowired
    private AsyncService asyncService;

    public void test() {
        asyncService.asyncMethod();
    }
}

这种写法有问题,因为异步方法是在另一个线程中执行的,而MyClass中的asyncService实例是被主线程创建的,如果直接在主线程中调用异步方法的话,就会引发异步任务被同步执行的问题。

正解是使用@Async注解来修饰类中的方法,因为使用@Async注解修饰的方法会被Spring AOP机制切入,并将其转化为异步执行。示例代码如下:

@Service
public class AsyncService {

    public void syncMethod() {
        // ...
    }

    @Async
    public void asyncMethod() {
        // ...
    }
}

@Component
public class MyClass {
    @Autowired
    private AsyncService asyncService;

    public void test() {
        asyncService.asyncMethod();
    }
}

这样就可以避免异步任务被同步执行的问题了。

2. 异步方法调用自身问题

异步方法调用自身是一个比较常见的问题,比如下面这样的代码会导致异步任务失效:

@Service
public class AsyncService {

    @Async
    public void test() {
        test();
    }
}

如果要在异步方法中实现循环调用,就需要使用另外一种异步调用的方式,即通过@Async和Future一起使用。示例代码如下:

@Service
public class AsyncService {

    @Async
    public Future<Void> test() {
        // do something
        return CompletableFuture.completedFuture(null);
    }

    public void init() {
        test().get(); // 阻塞,等待异步任务执行完成
    }
}

这样异步方法就可以实现自己的循环调用了。

最后总结一下,异步方法虽然在开发中能够提高效率,但需要注意一些细节问题。开发者需要充分理解异步方法的执行机制,并注意调用方式。如果掌握得当,就能够真正发挥异步方法的威力。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:spring boot项目使用@Async注解的坑 - Python技术站

(0)
上一篇 2023年5月19日
下一篇 2023年5月19日

相关文章

  • Java 判断两个字符串是否由相同的字符组成的实例

    下面是“Java 判断两个字符串是否由相同的字符组成的实例”的完整攻略。 鉴于这个问题,我们需要一个逐字比较的算法来解决。首先,需要确保两个字符串的长度相等,然后对它们进行排序,最后逐一比较它们是否相等。下面是具体步骤: 确保两个字符串的长度相等。可以使用 length() 方法来获取两个字符串的长度,并使用 if 语句确定它们是否相等,如果不相等,马上返回…

    Java 2023年5月27日
    00
  • Java线程之程安全与不安全代码示例

    我来详细讲解一下“Java线程之程安全与不安全代码示例”的完整攻略。 程序设计中的线程安全性 当我们在写多线程程序时,需要考虑一个非常重要的问题,那就是线程安全性。所谓线程安全,就是指当多个线程同时访问同一份数据时,能够保证数据的正确性和一致性。 线程安全性对于程序的正确性非常关键,如果程序中存在不安全的非线程安全代码,可能会造成意想不到的隐患,例如数据损坏…

    Java 2023年5月20日
    00
  • Spring中的事务管理如何配置

    Spring提供了声明式事务管理和编程式事务管理两种方式。本文主要介绍Spring中的声明式事务管理的配置方法。 1. 配置数据源及事务管理器 首先需要配置数据源,这里以MySQL为例,配置方法如下: <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDa…

    Java 2023年6月3日
    00
  • Java实战员工绩效管理系统的实现流程

    Java实战员工绩效管理系统的实现流程 本篇攻略主要讲解如何设计和实现一个员工绩效管理系统,以Java编程语言为基础,并且包括了以下几个方面的内容: 设计系统部件和功能模块 创建数据库结构和数据模型 开发业务功能和控制器 实现基于MVC架构的用户界面 部署系统到远程服务器 设计系统部件和功能模块 在设计系统的时候,需要考虑到员工绩效管理系统的核心功能,例如:…

    Java 2023年5月24日
    00
  • Hibernate的各种保存方式的区别详解

    下面是关于Hibernate的各种保存方式的区别详解的完整攻略。 Hibernate的各种保存方式 在Hibernate中,有四种保存方式,分别是:- save()方法- persist()方法- saveOrUpdate()方法- merge()方法 下面将详细介绍它们之间的区别。 save()方法 在Hibernate中,通过save()方法保存一个持久…

    Java 2023年5月19日
    00
  • 一文带你学会Spring JDBC的使用

    一文带你学会Spring JDBC的使用 简介 Spring JDBC是基于JDBC的框架,它提供了许多方便的功能去简化JDBC编码的繁琐。它可以自动管理连接、传播事务,同时提供了一种直观且简洁的方式去执行SQL语句,Spring JDBC已成为了Java应用程序中访问数据库的首选。本文将介绍如何使用Spring JDBC去连接数据库、执行SQL查询与更新,…

    Java 2023年5月19日
    00
  • 详解SpringBoot AOP 拦截器(Aspect注解方式)

    下面是详解 SpringBoot AOP 拦截器(Aspect 注解方式)的完整攻略,并附带两条示例。 什么是 AOP AOP(Aspect Oriented Programming,面向切面编程)是一种面向对象编程的编程思想,AOP 的思想是将系统分解为多个功能单元,称之为“切面”(Aspect),然后编写代码来定义这些切面。这些切面可以跨越多个类,不仅仅…

    Java 2023年5月19日
    00
  • Java中URL的处理方法详解

    Java中URL的处理方法详解 概述 在 Java 中,可以使用 java.net.URL 类来处理 URL(统一资源定位符)。 URL 是一个字符串,用来表示一个资源的地址。比如,一个网页的 URL 可以是 https://www.example.com/index.html。URL 通常由一个协议名、一个主机名、一个端口号和一个路径组成。 创建 URL …

    Java 2023年6月15日
    00
合作推广
合作推广
分享本页
返回顶部