Spring boot Spring云引导上下文加载两次ApplicationContextInitializer&;弹簧靴

Spring boot Spring云引导上下文加载两次ApplicationContextInitializer&;弹簧靴,spring-boot,spring-cloud,Spring Boot,Spring Cloud,在spring.factories文件中声明初始值设定项以创建spring启动启动器时,我们意识到这些初始值设定项加载了两次: 一次由Spring Cloud Boostrap上下文执行 一次通过Spring引导上下文 在我们的例子中,我们在docker容器中启动数据库,所以我们不想重复两次 根据这个问题,这是Spring Cloud的预期行为: 当问及boostrap上下文应该如何区别于“常规”应用程序上下文时,给出的答案是 检查上下文的ID 运行示例应用程序后,ConfigurableA

spring.factories
文件中声明初始值设定项以创建spring启动启动器时,我们意识到这些初始值设定项加载了两次:

  • 一次由Spring Cloud Boostrap上下文执行
  • 一次通过Spring引导上下文
在我们的例子中,我们在docker容器中启动数据库,所以我们不想重复两次

根据这个问题,这是Spring Cloud的预期行为:

当问及boostrap上下文应该如何区别于“常规”应用程序上下文时,给出的答案是

检查上下文的ID

运行示例应用程序后,
ConfigurableApplicationContext.getId()
默认返回:

  • 应用程序
    用于Spring云引导上下文
  • application-1
    用于Spring引导上下文
我们的一些用户不定义
spring.application.name
,其他用户根本不使用spring云

问题:我们如何才能可靠地只加载一次初始值设定项

如果
ApplicationContextInitializer
s是幂等的,那么它可能会出现在接口的Javadocs中


在最坏的情况下,我们如何安全地将Spring Cloud boostrap上下文与Spring启动上下文区分开来?

我们在尝试将属性源注入
环境后处理器时遇到了相同的问题。解决方案非常简单,因为您只需要一个静态标志:

public类初始值设定项实现ApplicationContextInitializer
{
私有静态布尔初始化=false;
@凌驾
public void初始化(ConfigurableApplicationContext applicationContext)
{
如果(!已初始化){
//在这里做你的事情
初始化=真;
}
}
}
引导应用程序上下文将始终在常规Spring引导应用程序上下文之前运行,因此您也可以使用它在正确的位置运行代码

最后,在
bootstrapplicationlistener
中实例化引导上下文。从那里,您可以看到
spring.application.name
属性被设置为
spring.cloud.bootstrap.name
bootstrap
的值,作为一种后备方法。然后将其设置为
ContextIdApplicationContextInitializer
中应用程序上下文的id。您还可以使用它来确定初始值设定项在哪个上下文中运行