Spring @Async的怪癖

时间:2013-06-13 13:36:18

标签: spring asynchronous annotations

我正在使用Spring的@Sync注释,我遇到了一些古怪的行为。我已经整理了一个非常简单的测试用例,它只是不起作用(我的异步方法没有被调用)。以某种方式调整测试用例确实会导致调用该方法,但很难理解为什么。无论如何,这里是细节。我正在使用基于注释的配置和自动装配。

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

a)Spring上下文文件:

<context:annotation-config />
<context:component-scan base-package="sample" />
<task:annotation-driven />

b)包含异步方法的类:

package sample;

@Component
public class SomeServiceImpl {
    @Async
    public void asynchMethod(String in) {
        logger.debug("Starting asynchMethod");
        logger.debug("Ending asynchMethod");
    }

    public void doNothing() {
    }
}

c)单元测试(在TestSomeService类中):

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

以下是单元测试结果:

[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。这个例子很简单,我不明白它为什么不起作用。

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

@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

我无法理解为什么第一次调用同步方法会使异步方法调用工作。

NEXT - 更令人费解的是:如果我在调用异步方法后让我的单元测试进入休眠状态一秒钟 - 异步方法会执行。

@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

我很困惑为什么简单的情况不起作用,以及为什么其他两个修改确实有效。谁能看到我错过的东西?

1 个答案:

答案 0 :(得分:2)

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