Необходимо переместить код в метод прослушивания событий и пометить метод с помощью @Async
.
. Убедитесь, что функция Asyn c установлена правильно. См .: Как сделать @ Asyn c в 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
.
UPDATE
Если вам нужно, чтобы приложение задержало завершение последовательности запуска до завершения всех асинхронных методов, я думаю, вам нужно обработать его самостоятельно.
Создать интерфейс AsyncInitializingBean
тем же методом, что и InitializingBean
, затем создайте @Component
с именем AsyncBeanInitializer
с автоматическим подключением AsyncInitializingBean[]
(или List
), а затем выполните все методы, используя ExecutorService
в ContextRefreshedEvent
.
@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();
}
}
}