Java 并行执行Spring初始化bean
我有多个SpringJava 并行执行Spring初始化bean,java,spring,initialization,Java,Spring,Initialization,我有多个SpringInitializingBean类,我希望它们都能并行运行AfterPropertieSet()。但是,当我运行一个小示例时,它们是同步执行的。有没有办法并行执行它们 下面是一个初始化bean的示例,可以用来测试我所指的内容。创建这样的多个类(即InitBeanOne,InitBeanTwo,…)时,日志显示它们正在同步运行 我想到的一个想法是让一个初始化bean异步初始化所需的类。不过,这是最后的选择,因为我想单独为每个类初始化bean,而不需要其他依赖类 @组件 公共类I
InitializingBean
类,我希望它们都能并行运行AfterPropertieSet()
。但是,当我运行一个小示例时,它们是同步执行的。有没有办法并行执行它们
下面是一个初始化bean的示例,可以用来测试我所指的内容。创建这样的多个类(即InitBeanOne
,InitBeanTwo
,…)时,日志显示它们正在同步运行
我想到的一个想法是让一个初始化bean异步初始化所需的类。不过,这是最后的选择,因为我想单独为每个类初始化bean,而不需要其他依赖类
@组件
公共类InitBean实现初始化bean{
私有最终静态记录器Logger=LoggerFactory.getLogger(InitBean.class);
@凌驾
public void afterPropertieSet()引发异常{
info(“BEGIN:InitBean”);
时间单位。秒。睡眠(5);
info(“END:InitBean”);
}
}
您应该将代码重新定位到事件侦听方法,并用@Async
标记该方法
确保已正确设置异步功能。请参阅:
您应该使该方法在Spring框架触发时被触发
警告:这样做,在调用此方法之前/期间可能会调用其他方法。如果该方法执行其他方法所需的任何类型的初始化,则需要处理该初始化,例如使用
更新 如果您需要应用程序延迟启动序列的完成,直到所有异步方法完成,我认为您需要自己处理它 使用与相同的方法创建接口
AsyncInitializingBean
,然后创建名为AsyncBeanInitializer
的@组件
自动连接AsyncInitializingBean[]
(或列表
),然后让它使用上下文刷新事件
上的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");
}
}
没问题!不过,我对这个建议有点担心。它在bean仍在初始化时启动应用程序服务器。我的最终目标是让所有初始化bean同时运行,并且在它们全部完成之前不启动应用程序服务器。我建议在每个组件中使用
CountDownLatch
来处理它,这样,如果一个组件速度慢,其他组件在完成后仍然可以运行,也就是说,应用程序(大部分)准备得更快。我认为这不能满足我的需要。初始化bean需要在应用服务器启动之前完成。这与组件之间的相互依赖性无关。相反,我正在寻找一种解决方案,让它们同时初始化,同时在应用程序被视为准备好接收流量之前完成。我认为Spring正在跟踪的一个类似的问题是这个问题。您对答案的最新更新符合要求+1.是否会有一个init方法
实现,从而不依赖于内部接口?如果不是,这是迄今为止最好的解决方案。
@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();
}
}
}