gpt4 book ai didi

java - 使用@Async 注释的方法未被异步调用,并且在应用程序上下文启动之前收到 ContextRefreshedEvent

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:08:11 26 4
gpt4 key购买 nike

我提出了两种情况,一种是使用 bean 工厂注册的 bean,另一种是通过自动扫描包中的注释定义(例如 @Component)创建的 bean。 bean 类使用用 @EventListener@Async 注释的方法监听 ContextRefreshedEvent,以便它被异步调用。

场景一

BlockingListener 类的单例被创建并注册到 bean 工厂。这是在初始化另一个 Bean 时完成的,如下面的方法 afterPropertiesSet 中所述。 ContextRefreshedEvent 已收到但未退出,因此应用程序未启动。它仍然被阻止。

@EnableAsync
@EnableScheduling
@EnableAutoConfiguration
@SpringBootApplication
public class SampleApp implements InitializingBean {

private final DefaultListableBeanFactory beanFactory;

@Autowired
public SampleApp(DefaultListableBeanFactory beanFactory) {
this.beanFactory = beanFactory;
}

@Override
public void afterPropertiesSet() {
String beanName = "blocking-listener";
Object bean = new BlockingListener();
beanFactory.registerBeanDefinition(beanName, rootBeanDefinition(bean.getClass()).getBeanDefinition());
beanFactory.registerSingleton(beanName, bean);
}

public static void main(final String... args) {
SpringApplication.run(SampleApp.class, args);
}

public static class BlockingListener {

@Async
@EventListener(ContextRefreshedEvent.class)
void block() throws InterruptedException {
Thread.sleep(Long.MAX_VALUE);
}

}

}

场景2

BlockingListener 类使用 @Component 注释,并且自动检测和创建 bean。 收到 ContextRefreshedEvent 但没有退出,但应用程序启动。

@EnableAsync
@EnableScheduling
@EnableAutoConfiguration
@SpringBootApplication
public class SampleApp {

private final DefaultListableBeanFactory beanFactory;

@Autowired
public SampleApp(DefaultListableBeanFactory beanFactory) {
this.beanFactory = beanFactory;
}

public static void main(final String... args) {
SpringApplication.run(SampleApp.class, args);
}

@Component
public static class BlockingListener {

@Async
@EventListener(ContextRefreshedEvent.class)
void block() throws InterruptedException {
Thread.sleep(Long.MAX_VALUE);
}

}

}

预期的行为是第二​​种情况,因为 ContextRefreshedEvent 预计将在上下文成功启动后发布。但是我无法弄清楚为什么在上下文启动之前向 bean 工厂动态注册的 bean 接收到事件,以及为什么它阻止上下文启动。

最佳答案

在场景 1 中,block() 的调用不会异步发生,因为注解 @Async 没有生效。

@Async正在处理 BeanPostProcessor , 即 AsyncAnnotationBeanPostProcessor那是用代理包装实例。但是,当您手动将 bean 添加到 bean 工厂时,不会应用后处理器。

您在给定设置中可以做的是手动应用后处理器:

bean = beanFactory.initializeBean(bean, beanName);
beanFactory.registerSingleton(beanName, bean);

关于java - 使用@Async 注释的方法未被异步调用,并且在应用程序上下文启动之前收到 ContextRefreshedEvent,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50838933/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com