加载上下文后,Spring java config start@Async方法

加载上下文后,Spring java config start@Async方法,java,spring,asynchronous,Java,Spring,Asynchronous,我需要一个POJO方法来异步执行,所以我用@Async对它进行了注释。我已使用适当的@ComponentScan将@EnableAsync添加到我的@Configuration类中。这里有一个供您运行的小测试用例 public class Test { public static void main(String[] args) throws InterruptedException { AnnotationConfigApplicationContext context

我需要一个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);
            }
        }
    }
}
公共类测试{
公共静态void main(字符串[]args)引发InterruptedException{
AnnotationConfigApplicationContext上下文=新的AnnotationConfigApplicationContext();
register(MyConfig.class);
context.refresh();
对象o=context.getBean(AsyncBean.class);
//((AsyncBean)o).doStuff();
系统输出打印ln(o);
}
@组件扫描(basePackages=“my.package”)
@使能同步
@配置
//@EnableScheduling
公共静态类MyConfig{
@豆子
公共AsyncBean()抛出InterruptedException{
AsyncBean b=新的AsyncBean();
返回b;
}
}
公共静态类AsyncBean{
//@计划(固定速率=10000L,初始延迟=1000L)
@异步的
public void doStuff()引发InterruptedException{
对于(int i=0;i<5;i++){
System.out.println(“异步循环”+i+“->”+Thread.currentThread().getId());
睡眠(1000L);
}
}
}
}
上面的代码将加载
注释ConfigApplicationContext
并退出。但是,如果我取消注释
/((AsyncBean)o).doStuff(),然后将在单独的线程中运行。为什么当配置被完全读取时,
@Async
方法没有启动?这就是我所期望的

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


Spring是否还需要实现其他功能才能知道它必须启动我的
@Async
方法?

@Async
不打算在加载
应用程序上下文后运行。它旨在在调用带注释的方法时异步运行该方法

如果希望在应用程序启动时运行方法,那么应该使用
@PostConstruct
注释(在非延迟加载的bean上)。如果您需要异步运行该方法,那么您将不得不更加棘手,因为您同时使用
@PostConstruct
@Async

编辑:

@Async
@Scheduled
之间的区别可能不是最清楚的。通常,
@Scheduled
用于告知下一次调用特定方法的时间,并且通常是周期性的
@Async
用于异步运行方法,也就是说,该方法将在启动后台线程以执行该方法的工作后立即返回


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

是否有任何文档更详细地描述了
@Async
@Scheduled
之间的差异?酷豆!谢谢你的回答。我刚刚偶然发现了这个答案,我得说它确实简化了我正在为一个项目修补的一些优化(异步填充缓存而不阻止我的服务器启动)。非常感谢你!另一个讨论线程提供了一个巧妙的解决方案:使用
@Scheduled(fixedRate=Long.MAX_VALUE
(请参阅)