@Async无法用于返回类型为void的方法

Dhr*_*del 4 java spring asynchronous spring-annotations spring-boot

我想做一个使用@Async注解以异步方式写入数据库的方法。

我用注解标记了该类@EnableAsync

@EnableAsync
public class FacialRecognitionAsyncImpl {

    @Async
    public void populateDataInPushQueue(int mediaId, int studentId) {
        //myCode
    }
}
Run Code Online (Sandbox Code Playgroud)

在调用该populateDataInPushQueue方法时,写操作应在另一个线程中执行,并且流程应从我正在调用此方法的类中继续。但这没有发生,程序执行正在等待此方法完成。

Nik*_*las 7

@Async注解有一些限制-检查是否这些得到尊重:

  • 它必须仅应用于public方法
  • 不能从定义的同一类中调用
  • 返回类型必须为voidFuture

在以下文档中可以找到以下内容@EnableAsync

请注意,代理模式仅允许通过代理拦截呼叫;同一类中的本地调用无法以这种方式被拦截。

另一个事实是,带有注释的类也@EnableAsync必须@Configuration也是。因此,从一个空类开始:

@EnableAsync
@Configuration
public class AsyncConfiguration { }
Run Code Online (Sandbox Code Playgroud)

  • 您不能只实例化一个新的FacialRecognitionAsyncImpl实例,然后调用async方法。异步功能(仅**)存在于Spring初始化应用程序上下文时创建的Spring代理对象上。您需要使“ FacialRecognitionAsyncImpl”成为Spring管理的组件(通过使用“ @Component”或等效的注释对其进行注释),并使用“ @Autowire”将组件注入服务器层的类中,然后调用异步该注入实例上的方法,该实例将是Spring管理的代理。 (5认同)

Ale*_*rov 4

在我看来,您缺少@Configuration注释,并且您的异步服务未经过组件扫描。下面是一个可以解决这个问题的示例代码片段:

@Configuration
@EnableAsync  //should be placed together.
public class FacialRecognitionAsyncService {

     @Async
     public void populateDataInPushQueue(int mediaId, int studentId) {
         //myCode
     }
} 

@Configuration
@EnableAsync
public class FacialServiceConfig {

    // this will make your service to be scanned.
    @Bean
    public FacialRecognitionAsyncService createFacialRecognitionService() {
        return new FacialRecognitionAsyncService();
    }

}
Run Code Online (Sandbox Code Playgroud)

现在是调用异步方法的服务 bean。请注意,它已被依赖注入。这样 Spring AOP 代理将在每次调用facialService. Spring在后台使用AOP来实现@Async

@Service
public class MyBusinessService {

@Autowire
FacialRecognitionAsyncService  facialService;

public myBusinessMethod() {
   facialService.populateDataInPushQueue()
}
Run Code Online (Sandbox Code Playgroud)

请注意,它FacialService是通过依赖注入注入的MyService