调用@Async方法时,Spring MVC控制器不会立即返回

Sri*_*ula 8 java spring spring-mvc

我正在使用spring注释来配置控制器(@EnableWebMvc),服务(@service和@ComponentScan).在我的一个服务中,我有一个用@Async注释的方法,我在配置类上也添加了@EnableAsync.当其中一个MVC控制器调用使用@Async注释的服务方法时,我希望控制器立即返回,而不必等待服务方法完成.由它没有.当我在服务方法中设置断点时,我发现它实际上是在一个单独的线程中运行,即堆栈跟踪确实显示它正在使用我在下面配置的SimpleAsyncTaskExecutor.

这是我的配置类中的注释

@Configuration
@EnableWebMvc
@EnableScheduling
@ComponentScan(basePackages = "com.mypackage")
@EnableAsync
public class WebApplicationConfig extends WebMvcConfigurerAdapter implements AsyncConfigurer {
...
...
@Override
    public Executor getAsyncExecutor() {
        SimpleAsyncTaskExecutor executor = new SimpleAsyncTaskExecutor("SimpleExecutor-");
        executor.setConcurrencyLimit(props.getIntegerProperty(SysProps.EMAIL_SENDER_CONCURRENT_THREAD_LIMIT));
        return executor;
    }
Run Code Online (Sandbox Code Playgroud)

这是我的MVC控制器方法看起来像

    @Autowired 
    private EmailService emailService;
    @ResponseStatus(value = HttpStatus.CREATED)
    @RequestMapping(value = "/asset/{assetId}/slideshare/email", method = RequestMethod.POST, produces = JSON_UTF8)
    @ResponseBody
    @ApiResponseObject
    public Link createAndEmailSlideShareLink(@PathVariable final String assetId,
                                             @RequestParam(value = "email") final String email,
                                             @RequestParam(value = "message", required = false) final String message,
                                             final HttpServletRequest request) {
    Link link = linkService.createLink()
    emailService.sendSlideShareAssetEmail(user,link...
    return link;
}
Run Code Online (Sandbox Code Playgroud)

服务方法看起来像这样

@Async
public void sendSlideShareAssetEmail(User user, String email, String msg, String link, Asset asset) {
Run Code Online (Sandbox Code Playgroud)

为什么MVC控制器没有立即返回?

Rya*_*yan 0

我的猜测是您的 EmailService bean 是从两个不同的上下文中包含的。

Ryan Stewart 的回答更详细地解释了问题/解决方案。

您还有正在使用的其他配置吗?您的 web.xml 中是否定义了 *-servlet.xml 或其他 servlet,可能会将您的 EmailService 引入根上下文?

您是否定义了 ContextLoaderListener 或 ServletContextListener?除了组件扫描之外,也许这些还会获取您的电子邮件服务。

将整个源树作为组件扫描路径似乎很可疑。尝试限制您在组件扫描中使用的路径以排除您的 EmailService,并查看它是否仍在 SimpleAsyncTaskExecutor 中运行。如果是的话,你就知道它是从不同的背景中引入的。一旦找到其他上下文,您应该能够将其排除在那里,并将其添加回其他上下文中的组件扫描或 EnableAsync 中。