gpt4 book ai didi

java - 并行执行 Spring 初始化 Bean

转载 作者:行者123 更新时间:2023-12-02 08:55:42 26 4
gpt4 key购买 nike

我有多个 Spring InitializingBean 类,我希望它们都并行运行 afterPropertiesSet()。然而,当我运行一个小示例时,它们是同步执行的。有什么办法可以并行执行它们吗?

下面是一个初始化 bean 的示例,可用于测试我所指的内容。当创建多个这样的类(即 InitBeanOneInitBeanTwo...)时,日志显示它们正在同步运行。

我想到的一个想法是让一个初始化 bean 异步初始化所需的类。不过,这是最后的选择,因为我想单独利用每个类的初始化 bean,而不需要其他依赖类。

@Component
public class InitBean implements InitializingBean {

private final static Logger LOGGER = LoggerFactory.getLogger(InitBean.class);

@Override
public void afterPropertiesSet() throws Exception {
LOGGER.info("BEGIN: InitBean");
TimeUnit.SECONDS.sleep(5);
LOGGER.info("END: InitBean");
}
}

最佳答案

您应该将代码重新定位到事件监听方法,并使用@Async标记该方法。

确保异步功能设置正确。请参阅:How To Do @Async in Spring .

您应该让该方法在 Spring 框架触发 ApplicationReadyEvent 时被触发。 .

@Component
public class InitBean {
private final static Logger LOGGER = LoggerFactory.getLogger(InitBean.class);

@Async
@EventListener
public void onApplicationReady(ApplicationReadyEvent event) throws Exception {
LOGGER.info("BEGIN: onApplicationReady");
TimeUnit.SECONDS.sleep(5);
LOGGER.info("END: onApplicationReady");
}
}

警告:通过这样做,可能会在调用此方法之前/期间调用其他方法。如果该方法执行其他方法所需的任何类型的初始化,您需要处理它,例如使用CountDownLatch .

<小时/>

更新

如果您需要应用程序延迟启动序列的完成,直到所有异步方法完成,我认为您需要自己处理。

使用与InitializingBean相同的方法创建接口(interface)AsyncInitializingBean ,然后创建一个名为 AsyncBeanInitializer@Component Autowiring AsyncInitializingBean[] (或 List),然后它使用 ContextRefreshedEvent 上的 ExecutorService 执行所有方法。

@Component
public class InitBean implements AsyncInitializingBean { // <== Change interface (only change needed)

private final static Logger LOGGER = LoggerFactory.getLogger(InitBean.class);

@Override
public void afterPropertiesSet() throws Exception {
LOGGER.info("BEGIN: InitBean");
TimeUnit.SECONDS.sleep(5);
LOGGER.info("END: InitBean");
}
}
public interface AsyncInitializingBean {
void afterPropertiesSet() throws Exception;
}
@Component
public class AsyncBeanInitializer {
private final static Logger LOGGER = LoggerFactory.getLogger(AsyncBeanInitializer.class);

@Autowired(required = false)
private AsyncInitializingBean[] beans;

@EventListener
public void onContextRefreshed(@SuppressWarnings("unused") ContextRefreshedEvent event) throws Exception {
if (this.beans == null || this.beans.length == 0)
return;
ExecutorService executorService = Executors.newWorkStealingPool();
try {
AtomicInteger failed = new AtomicInteger();
for (AsyncInitializingBean bean : beans) {
executorService.submit(() -> {
try {
bean.afterPropertiesSet();
} catch (Exception e) {
failed.incrementAndGet();
LOGGER.error("Async afterPropertiesSet() method failed: " + e, e);
}
});
}
executorService.shutdown();
executorService.awaitTermination(60, TimeUnit.MINUTES);
if (failed.get() != 0)
throw new RuntimeException(failed.get() + " Async afterPropertiesSet() methods failed. See log for details.");
} finally {
executorService.shutdownNow();
}
}
}

关于java - 并行执行 Spring 初始化 Bean,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60497894/

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