我正在使用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;
}
这是我的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;
}
服务方法看起来像这样
@Async
public void sendSlideShareAssetEmail(User user, String email, String msg, String link, Asset asset) {
为什么MVC控制器没有立即返回?
答案 0 :(得分:0)
我的猜测是你的EmailService bean是从两个不同的上下文中包含的。
此answer from Ryan Stewart更详细地解释了问题/解决方案。
您是否有其他正在使用的配置?您的web.xml中是否定义了* -servlet.xml或其他servlet,可能会将您的EmailService带入根上下文?
您是否定义了ContextLoaderListener或ServletContextListener?除了组件扫描之外,也许这些人正在拿起你的EmailService。
将整个源树包含为组件扫描路径似乎是可疑的。 尝试限制在组件扫描中使用的路径以排除您的EmailService,并查看它是否仍在SimpleAsyncTaskExecutor中执行。如果不是你知道它是从不同的环境中引入的。找到其他上下文后,您应该能够将其排除在那里并将其添加回组件扫描或其他上下文中的EnableAsync。