在spring.factories
文件中声明初始化程序以创建Spring Boot启动程序时,我们意识到这些初始化程序已加载两次:
在我们的例子中,我们在docker容器中启动数据库,所以我们不想重复两次。
根据此问题,这是Spring Cloud的预期行为:https://github.com/spring-cloud/spring-cloud-config/issues/1151
当询问应该如何将boostrap上下文与“常规”应用程序上下文区分开时,给出的答案是
检查上下文的ID。
运行示例应用程序后,ConfigurableApplicationContext.getId()
默认返回:
application
用于Spring Cloud Bootstrap上下文application-1
用于Spring Boot上下文我们的某些用户没有定义spring.application.name
,其他用户根本没有使用Spring Cloud。
问题:如何仅一次可靠地加载初始化程序?
如果ApplicationContextInitializer
应该是幂等的,则应该在接口的Javadocs中找到它。
在最坏的情况下,我们如何安全地将Spring Cloud boostrap上下文与Spring Boot上下文区分开?
答案 0 :(得分:0)
当尝试在EnvironmentPostProcessor
here中注入属性源时,我们遇到了相同的问题。解决方案非常简单,因为您只需要一个静态标志:
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
中的应用程序上下文的ID。您还可以使用它来确定初始化程序在哪个上下文中运行。