4

我需要一个 POJO 方法来异步执行,所以我用@Async. 我已经@EnableAsync@Configuration正确的@ComponentScan. 这是一个供您运行的小测试用例。

public class Test {
    public static void main(String[] args) throws InterruptedException {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        context.register(MyConfig.class);
        context.refresh();
        Object o = context.getBean(AsyncBean.class);

        //((AsyncBean)o).doStuff();

        System.out.println(o);

    }

    @ComponentScan(basePackages = "my.package")
    @EnableAsync
    @Configuration
    // @EnableScheduling
    public static class MyConfig {
        @Bean
        public AsyncBean bean() throws InterruptedException {
            AsyncBean b = new AsyncBean();
            return b;
        }
    }

    public static class AsyncBean {
        //@Scheduled(fixedRate = 10000L, initialDelay = 1000L)
        @Async
        public void doStuff() throws InterruptedException {
            for (int i = 0; i < 5; i++) {
                System.out.println("async loop" + i + " -> " + Thread.currentThread().getId());
                Thread.sleep(1000L);
            }
        }
    }
}

上面的代码将加载AnnotationConfigApplicationContext并退出。但是,如果我取消注释//((AsyncBean)o).doStuff();,那么它将在单独的线程中运行。为什么@Async读取完配置后方法没有启动?这就是我所期望的。

我在@Scheduled上面留下了一些东西,所以你可以自己试试。在 的情况下@Scheduled,带注释的方法会立即被触发(即在初始延迟之后)。

@Async为了让 Spring 知道它必须启动我的方法,我还需要实现其他什么吗?

4

1 回答 1

17

@Async不打算在加载ApplicationContext. 它旨在在调用时异步运行带注释的方法。

如果您希望某个方法在应用程序启动时运行,那么您应该使用@PostConstruct注解(在非延迟加载的 bean 上)。如果您需要该方法异步运行,那么您将不得不更加棘手,因为您同时使用这两种@PostConstruct方法@Async如 25.5.2 的最后一段所述)。

编辑:

@Async和之间的区别@Scheduled可能不是从文档中最清楚的。通常,@Scheduled用于告诉何时应该对特定方法进行下一次调用,并且通常是周期性的。 @Async用于异步运行方法,即在启动后台线程完成方法的工作后,方法会立即返回。

令人困惑的部分是后台线程。他们都使用一个,但是他们尝试做的事情的性质是不同的(通常是非用户交互的定期后台工作与通常由用户发起的一次性后台工作)。

于 2013-05-27T22:48:40.207 回答