Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 并行执行Spring初始化bean_Java_Spring_Initialization - Fatal编程技术网

Java 并行执行Spring初始化bean

Java 并行执行Spring初始化bean,java,spring,initialization,Java,Spring,Initialization,我有多个SpringInitializingBean类,我希望它们都能并行运行AfterPropertieSet()。但是,当我运行一个小示例时,它们是同步执行的。有没有办法并行执行它们 下面是一个初始化bean的示例,可以用来测试我所指的内容。创建这样的多个类(即InitBeanOne,InitBeanTwo,…)时,日志显示它们正在同步运行 我想到的一个想法是让一个初始化bean异步初始化所需的类。不过,这是最后的选择,因为我想单独为每个类初始化bean,而不需要其他依赖类 @组件 公共类I

我有多个Spring
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();
        }
    }
}