Spring@Async的怪癖

Spring@Async的怪癖,spring,asynchronous,annotations,Spring,Asynchronous,Annotations,我正在考虑使用Spring的@Sync注释,我遇到了一些奇怪的行为。我已经准备了一个非常简单的测试用例,但它不起作用(我的异步方法没有被调用)。以某些方式调整测试用例确实会导致调用该方法,但很难理解为什么。不管怎么说,这里是详细情况。我正在使用基于注释的配置和自动布线 我已经用Spring 3.1.1和3.2.3进行了测试 a) Spring上下文文件: <context:annotation-config /> <context:component-scan base-pac

我正在考虑使用Spring的@Sync注释,我遇到了一些奇怪的行为。我已经准备了一个非常简单的测试用例,但它不起作用(我的异步方法没有被调用)。以某些方式调整测试用例确实会导致调用该方法,但很难理解为什么。不管怎么说,这里是详细情况。我正在使用基于注释的配置和自动布线

我已经用Spring 3.1.1和3.2.3进行了测试

a) Spring上下文文件:

<context:annotation-config />
<context:component-scan base-package="sample" />
<task:annotation-driven />
c) 单元测试(类内TestSomeService):

以下是单元测试结果:

[DEBUG] [2013-06-13 09:18:10,350] [sample.TestSomeService] - Starting testAsynch
[DEBUG] [2013-06-13 09:18:10,353] [sample.TestSomeService] - Ending testAsynch
异步方法没有输出-这就是问题1。这个例子很简单,我不明白为什么它不起作用

下一步-如果我通过添加对同步方法“doNothing()”的调用来修改测试:

无法执行异步方法:

[DEBUG] [2013-06-13 09:20:59,493] [sample.TestSomeService] - Starting testAsynch
[DEBUG] [2013-06-13 09:20:59,515] [sample.TestSomeService] - Ending testAsynch
[DEBUG] [2013-06-13 09:20:59,515] [sample.SomeServiceImpl] - Starting asynchMethod
[DEBUG] [2013-06-13 09:20:59,515] [sample.SomeServiceImpl] - Ending asynchMethod
我不明白为什么首先调用同步方法会使异步方法调用工作

接下来——更令人费解的是:如果我在调用异步方法后让单元测试休眠一秒钟——异步方法就会执行

@Test
public void testAsynch() throws InterruptedException {
    logger.debug("Starting testAsynch");
    service.asynchMethod("hello asynch");
    Thread.sleep(1000);
    logger.debug("Ending testAsynch");
}


[DEBUG] [2013-06-13 09:22:21,187] [sample.TestSomeService] - Starting testAsynch
[DEBUG] [2013-06-13 09:22:21,209] [sample.SomeServiceImpl] - Starting asynchMethod
[DEBUG] [2013-06-13 09:22:21,209] [sample.SomeServiceImpl] - Ending asynchMethod
[DEBUG] [2013-06-13 09:22:22,190] [sample.TestSomeService] - Ending testAsynch

我很困惑,为什么这个简单的案例不起作用,为什么其他两个修改可以起作用。有人能看到我遗漏了什么吗?

在执行异步调用的线程有机会运行之前,Junit运行结束(JVM停止),因此休眠会有所帮助。

在第一个示例中,异步应该正在执行。您的记录器有问题,它的定义在哪里?您可以在Async方法中尝试System.out.println来验证这一点。@dmitrisli:为了可读性,我省略了一些代码。我使用log4j记录器,如下所示:private static final Logger Logger=Logger.getLogger(SomeServiceImpl.class);我在System.out.println中得到了相同的结果。我怀疑这是正确的-但是你知道为什么在异步调用之前插入同步调用会使事情顺利进行吗?可能与生成的字节码中的计时和/或排序有关。我不会担心的。
@Test
public void testAsynch() throws InterruptedException {
    logger.debug("Starting testAsynch");
    service.doNothing();
    service.asynchMethod("hello asynch");
    logger.debug("Ending testAsynch");
}
[DEBUG] [2013-06-13 09:20:59,493] [sample.TestSomeService] - Starting testAsynch
[DEBUG] [2013-06-13 09:20:59,515] [sample.TestSomeService] - Ending testAsynch
[DEBUG] [2013-06-13 09:20:59,515] [sample.SomeServiceImpl] - Starting asynchMethod
[DEBUG] [2013-06-13 09:20:59,515] [sample.SomeServiceImpl] - Ending asynchMethod
@Test
public void testAsynch() throws InterruptedException {
    logger.debug("Starting testAsynch");
    service.asynchMethod("hello asynch");
    Thread.sleep(1000);
    logger.debug("Ending testAsynch");
}


[DEBUG] [2013-06-13 09:22:21,187] [sample.TestSomeService] - Starting testAsynch
[DEBUG] [2013-06-13 09:22:21,209] [sample.SomeServiceImpl] - Starting asynchMethod
[DEBUG] [2013-06-13 09:22:21,209] [sample.SomeServiceImpl] - Ending asynchMethod
[DEBUG] [2013-06-13 09:22:22,190] [sample.TestSomeService] - Ending testAsynch