При объявлении инициализаторов в файле spring.factories для создания стартеров Spring Boot мы поняли, что эти инициализаторы загружаются дважды:
В нашем случае мы запускаем базы данных в контейнерах докеров, поэтому мы не хотим делать это дважды.
Согласно этой проблеме, это ожидаемое поведение Spring Cloud: https://github.com/spring-cloud/spring-cloud-config/issues/1151
На вопрос, как следует отличать контекст Boostrap от «обычного» контекста приложения, следует ответить:
Check the ID of the context.
После запуска примера приложения ConfigurableApplicationContext.getId() по умолчанию возвращается:
application для контекста Spring Cloud Bootstrapapplication-1 для контекста Spring BootНекоторые из наших пользователей не определяют spring.application.name, другие вообще не используют Spring Cloud.
Вопрос: Как мы можем надежно загрузить инициализатор только один раз?
Если ApplicationContextInitializer должны быть идемпотентными, он, вероятно, должен фигурировать в документации Javadoc интерфейса.
В худшем случае, как мы можем безопасно отличить контекст Boostrap Spring Cloud от контекста Spring Boot?




Мы столкнулись с той же проблемой при попытке внедрить источник свойств в EnvironmentPostProcessorздесь. Решение довольно простое, вам нужен только статический флаг:
public class YourInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext>
{
private static boolean initialized = false;
@Override
public void initialize(ConfigurableApplicationContext applicationContext)
{
if (!initialized) {
//do your things here
initialized = true;
}
}
}
Контекст приложения начальной загрузки всегда будет запускать до обычный контекст приложения Spring Boot, поэтому вы также можете использовать его для запуска своего кода в нужном месте.
Наконец, контекст начальной загрузки создается в BootstrapApplicationListener. Отсюда вы можете видеть, что для свойства spring.application.name в качестве запасного варианта устанавливается значение spring.cloud.bootstrap.name или bootstrap. Затем он устанавливается на идентификатор контекста приложения в ContextIdApplicationContextInitializer. Вы также можете использовать это, чтобы определить, в каком контексте работает ваш инициализатор.