ApplicationContextInitializer загружается дважды в контексте начальной загрузки Spring Cloud и Spring Boot - PullRequest
0 голосов
/ 02 января 2019

При объявлении инициализаторов в файле spring.factories для создания стартеров Spring Boot мы поняли, что эти инициализаторы были загружены дважды:

  • один раз в контексте Boostrap Spring Cloud
  • один раз вконтекст Spring Boot

В нашем случае мы запускаем базы данных в Docker-контейнерах, поэтому мы не хотим делать это дважды.

В соответствии с этой проблемой это Spring Cloudожидаемое поведение: https://github.com/spring-cloud/spring-cloud-config/issues/1151

На вопрос, как следует отличать контекст boostrap от «обычного» контекста приложения, вы получите ответ:

Проверьте идентификатор контекста.

После запуска примера приложения по умолчанию возвращается ConfigurableApplicationContext.getId():

  • application для контекста начальной загрузки Spring Cloud
  • application-1 дляконтекст Spring Boot

Некоторые из наших пользователей не определяют spring.application.name, другие вообще не используют Spring Cloud.

Вопрос : Какмы можем надежно загрузить инициализатор только один раз?

Если ApplicationContextInitializer s предназначены для идемпотентности, это, вероятно, должно фигурировать в Javadocs интерфейса.

В худшем случае, как мы можем безопасно отличить контекст надстройки Spring Cloud от SpringКонтекст загрузки?

1 Ответ

0 голосов
/ 05 января 2019

Мы столкнулись с той же проблемой, когда пытались внедрить источник свойства в 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. Вы также можете использовать это, чтобы определить, в каком контексте работает ваш инициализатор.

...