我需要一个异步执行的POJO方法,所以我用@Async
注释了它。我用适当的@ComponentScan
将@EnableAsync
添加到我的@Configuration
类中。这里有一个小测试用例供您运行。
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
方法?
@Async
不打算在加载ApplicationContext
之后运行。它旨在在调用带注释的方法时异步运行该方法。
如果你想让一个方法在应用程序启动时运行,那么你应该使用@PostConstruct
注释(在非惰性加载bean上)。如果你需要异步运行该方法,那么你将不得不更狡猾一点,因为你同时使用@PostConstruct
和@Async
(如25.5.2的最后一段所述)。
@Async
和@Scheduled
之间的差异从文档中可能不是最清楚的。一般来说,@Scheduled
用于告诉何时应该发生对特定方法的下一次调用,并且通常是周期性的。@Async
用于异步运行方法,也就是说,该方法将在启动后台线程完成该方法的工作后立即返回。
令人困惑的部分是后台线程。它们都使用一个,但是它们试图做的事情的性质是不同的(周期性的后台工作,通常是非用户交互的,而一次性的后台工作通常是由用户发起的)。