控制器中的Spring Boot @Async方法同步执行

我的[基本] Spring Boot应用程序接受来自浏览器的请求,通过jQuery.get()发送,并且应该立即收到响应 – 例如“ 您的请求已经排队 ”。 为此,我写了一个控制器:

 @Controller public class DoSomeWorkController { @Autowired private final DoWorkService workService; @RequestMapping("/doSomeWork") @ResponseBody public String doSomeWork() { workService.doWork(); // time consuming operation return "Your request has been queued."; } } 

DoWorkServiceImpl类实现了DoWorkService接口,非常简单。 它有一种方法来执行耗时的任务。 我不需要从此服务调用返回任何内容,因为电子邮件将在工作结束时发送,包括失败或成功方案。 所以它实际上看起来像:

 @Service public class DoWorkServiceImpl implements DoWorkService { @Async("workExecutor") @Override public void doWork() { try { Thread.sleep(10 * 1000); System.out.println("completed work, sent email"); } catch (InterruptedException ie) { System.err.println(ie.getMessage()); } } } 

我认为这会有效,但浏览器的Ajax请求在返回响应之前等待了10秒。 所以控制器映射方法正在调用同步注释@Async的内部方法,看起来如此。 在传统的Spring应用程序中,我通常会将其添加到XML配置中:

   

所以我认为在主应用程序类中编写相同的东西会有所帮助:

 @SpringBootApplication @EnableAsync public class Application { @Value("${pool.size:1}") private int poolSize;; @Value("${queue.capacity:0}") private int queueCapacity; @Bean(name="workExecutor") public TaskExecutor taskExecutor() { ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); taskExecutor.setMaxPoolSize(poolSize); taskExecutor.setQueueCapacity(queueCapacity); taskExecutor.afterPropertiesSet(); return taskExecutor; } public static void main(String[] args) { SpringApplication.run(Application.class, args); } } 

这并没有改变这种行为。 发送请求10秒后,Ajax响应仍然到达。 我错过了什么?

Spring Boot应用程序可以在这里下载 。 安装Maven后,可以使用简单命令运行项目:

 mvn clean spring-boot:run 

注意由于下面的@Dave Syer提供的答案,问题已得到解决,他指出我在我的应用程序中缺少@EnableAsync ,即使我在上面的代码片段中有这一行。

您正在从同一个类中的另一个方法调用@Async方法。 除非您为@EnableAsync启用AspectJ代理模式(并且当然提供编织器),否则将无效(谷歌“代理自我调用”)。 最简单的解决方法是将@Async方法放在另一个@Bean

对于那些仍在寻找@Asnyc中所有步骤的人,只需简单的解释,这就是答案:

这是一个使用@Async的简单示例。 按照以下步骤使@Async在Spring Boot应用程序中工作:

步骤1:添加@EnableAsync注释并将TaskExecutor Bean添加到Application Class。

例:

 @SpringBootApplication @EnableAsync public class AsynchronousSpringBootApplication { private static final Logger logger = LoggerFactory.getLogger(AsynchronousSpringBootApplication.class); @Bean(name="processExecutor") public TaskExecutor workExecutor() { ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor(); threadPoolTaskExecutor.setThreadNamePrefix("Async-"); threadPoolTaskExecutor.setCorePoolSize(3); threadPoolTaskExecutor.setMaxPoolSize(3); threadPoolTaskExecutor.setQueueCapacity(600); threadPoolTaskExecutor.afterPropertiesSet(); logger.info("ThreadPoolTaskExecutor set"); return threadPoolTaskExecutor; } public static void main(String[] args) throws Exception { SpringApplication.run(AsynchronousSpringBootApplication.class,args); } } 

第2步:添加执行异步过程的方法

 @Service public class ProcessServiceImpl implements ProcessService { private static final Logger logger = LoggerFactory.getLogger(ProcessServiceImpl.class); @Async("processExecutor") @Override public void process() { logger.info("Received request to process in ProcessServiceImpl.process()"); try { Thread.sleep(15 * 1000); logger.info("Processing complete"); } catch (InterruptedException ie) { logger.error("Error in ProcessServiceImpl.process(): {}", ie.getMessage()); } } } 

步骤3:在Controller中添加API以执行异步处理

 @Autowired private ProcessService processService; @RequestMapping(value = "ping/async", method = RequestMethod.GET) public ResponseEntity> async() { processService.process(); Map response = new HashMap<>(); response.put("message", "Request is under process"); return new ResponseEntity<>(response, HttpStatus.OK); } 

我还在GitHub上写了一个博客和一个有用的应用程序。 请检查: http : //softwaredevelopercentral.blogspot.com/2017/07/asynchronous-processing-async-in-spring.html

我有一个类似的问题,我在正确的bean中有@Async和@EnableAsync注释,但仍然是同步执行的方法。 检查完日志之后有一个警告说我有多个ThreadPoolTask​​Executor类型的bean,而且没有一个叫做taskExecutor所以……

 @Bean(name="taskExecutor") public ThreadPoolTaskExecutor defaultTaskExecutor() { ThreadPoolTaskExecutor pool = new ThreadPoolTaskExecutor(); //Thread pool configuration //... return pool; } 

有关线程池可用的配置,请参见http://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/scheduling/concurrent/ThreadPoolTask​​Executor.html 。

按照以下三个步骤:

1步:将@EnableAsync与@configuration或@SpringBootApplication一起使用

@EnableAsync公共类Application {

2步骤:

 /** * THIS FOR ASYNCRONOUS PROCESS/METHOD * @return */ @Bean public Executor asyncExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(5); executor.setMaxPoolSize(5); executor.setQueueCapacity(500); executor.setThreadNamePrefix("Anycronous Process-"); executor.initialize(); return executor; } 

3步骤:将@Async放在预期的方法上

Ť