Zacard's Notes

spring3的@Async异步执行失效

背景

最近有个项目的spring的@Async的异步执行突然失效了。生产环境异步执行正常,那肯定是开发改了某个地方而导致的。

排查

查看最近提交代码记录。与@Async有相关的改动只有一个spring.xml的改动。初步推断是这个改动引起的。回滚这部分代码,跑测试类,果然异步执行生效了。

原因

在stackoverflow中找到了答案:

In short, the context loaded by the ContextLoaderListener (generally from applicationContext.xml) is the parent of the context loaded by the DispatcherServlet (generally from -servlet.xml). If you have the bean with the @Async method declared/component-scanned in both contexts, the version from the child context (DispatcherServlet) will override the one in the parent context (ContextLoaderListener). I verified this by excluding that component from component scanning in the -servlet.xml – it now works as expected.

意思是说:如果项目中存在多个配置文件(例如:applicationContext.xml、applicationContext-servlet.xml)并且这两个文件中配置的扫描包(即配置的:context:component-scan)都包含了配置过@Async的bean,那么后者就会覆盖前者。

例如以下xml配置:

applicationContext.xml:

<context:component-scan base-package="com.demo" />
<task:annotation-driven/>
<task:executor id="executor" pool-size="5-10" queue-capacity="100" rejection-policy="CALLER_RUNS"/>

applicationContext-servlet.xml:

<context:component-scan base-package="com.demo" />

并且在web.xml中配置的加载顺序为:applicationContext.xml > applicationContext-servlet.xml,那么后者的component-scan就会覆盖前者的,同时前者配置的task也会被覆盖掉不起作用!

坚持原创技术分享,您的支持将鼓励我继续创作!

热评文章