bootstrap.yml(bootstrap.properties)用来程序引导时执行,应用于更加早期配置信息读取,如可以使用来配置application.yml中使用到参数等
application.yml(application.properties) 应用程序特有配置信息,可以用来配置后续各个模块中需使用的公共参数等。
加载过程中,配置文件加载顺序为:
bootstrap.yml > application.yml > application-dev(prod).yml
通过对代码进行Debug发现SpringApplication#run(…)方法被调用了3次。
项目结构:
监控加载的配置文件,断点设置在:ConfigFileApplicationListener#load(…) 501行,可以监控都读取了哪些配置文件。
最终监控到执行SpringApplication#run(args)的顺序:
1)第一次SpringApplication#run() args为{}
SpringBoot入口类
@SpringBootApplication(scanBasePackages = {"com.dx"}, proxyBeanMethods = false)
@EnableFeignClients(basePackages = {"com.dx.domain.feign"})
@EnableShackleTemplates(basePackages = {"com.dx.service"})
@EnableEurekaClient
public class App {
/**
* 主程序入口(jar格式)
* @param args 命令行参数
* @throws Exception 执行异常
*/
public static void main(String[] args) throws Exception {
configureApplication(new SpringApplicationBuilder()).run(args);
}
/**
* 定义程序入口
* @param builder SpringApplicationBuilder
* @return SpringApplicationBuilder
*/
private static SpringApplicationBuilder configureApplication(SpringApplicationBuilder builder) {
return builder.sources(App.class).bannerMode(Banner.Mode.CONSOLE).logStartupInfo(true)
.registerShutdownHook(true).web(WebApplicationType.SERVLET);
}
}
2)第一次SpringApplication#run()执行到SpringApplication#prepareEnvironment(…)执行第二次SpringApplication#run()
返回context:
org.springframework.context.annotation.AnnotationConfigApplicationContext@7876d598, started on Tue Mar 13 11:10:31 CST 2021
SpringApplication#run(String… args)运行流程:
SpringApplication#run(String... args)
|-ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
SpringApplication#prepareEnvironment(SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments)
|-listeners.environmentPrepared((ConfigurableEnvironment)environment);
SpringApplicationRunListeners#environmentPrepared(ConfigurableEnvironment environment)
|-listener.environmentPrepared(environment);
EventPublishingRunListener#environmentPrepared(ConfigurableEnvironment environment)
|-this.initialMulticaster.multicastEvent(new ApplicationEnvironmentPreparedEvent(this.application, this.args, environment));
SimpleApplicationEventMulticaster#multicastEvent(ApplicationEvent event)
|-constructor(...)
SimpleApplicationEventMulticaster#multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType)
|-this.invokeListener(listener, event);
SimpleApplicationEventMulticaster#invokeListener(ApplicationListener listener, ApplicationEvent event)
|-this.doInvokeListener(listener, event);
SimpleApplicationEventMulticaster#doInvokeListener(ApplicationListener listener, ApplicationEvent event)
|-listener.onApplicationEvent(event);
BootstrapApplicationListener#onApplicationEvent(ApplicationEnvironmentPreparedEvent event)
|-context = this.bootstrapServiceContext(environment, event.getSpringApplication(), configName);
BootstrapApplicationListener#bootstrapServiceContext(ConfigurableEnvironment environment, final SpringApplication application, String configName)
BootstrapApplicationListener#bootstrapServiceContext(…)源码分析:
private ConfigurableApplicationContext bootstrapServiceContext(ConfigurableEnvironment environment, final SpringApplication application, String configName) {
StandardEnvironment bootstrapEnvironment = new StandardEnvironment();
MutablePropertySources bootstrapProperties = bootstrapEnvironment.getPropertySources();
Iterator var6 = bootstrapProperties.iterator();
while(var6.hasNext()) {
PropertySource source = (PropertySource)var6.next();
bootstrapProperties.remove(source.getName());
}
String configLocation = environment.resolvePlaceholders("${spring.cloud.bootstrap.location:}");
String configAdditionalLocation = environment.resolvePlaceholders("${spring.cloud.bootstrap.additional-location:}");
Map bootstrapMap = new HashMap();
bootstrapMap.put("spring.config.name", configName);
bootstrapMap.put("spring.main.web-application-type", "none");
if (StringUtils.hasText(configLocation)) {
bootstrapMap.put("spring.config.location", configLocation);
}
if (StringUtils.hasText(configAdditionalLocation)) {
bootstrapMap.put("spring.config.additional-location", configAdditionalLocation);
}
bootstrapProperties.addFirst(new MapPropertySource("bootstrap", bootstrapMap));
Iterator var9 = environment.getPropertySources().iterator();
while(var9.hasNext()) {
PropertySource source = (PropertySource)var9.next();
if (!(source instanceof StubPropertySource)) {
bootstrapProperties.addLast(source);
}
}
SpringApplicationBuilder builder = (new SpringApplicationBuilder(new Class[0])).profiles(environment.getActiveProfiles()).bannerMode(Mode.OFF).environment(bootstrapEnvironment).registerShutdownHook(false).logStartupInfo(false).web(WebApplicationType.NONE);
SpringApplication builderApplication = builder.application();
if (builderApplication.getMainApplicationClass() == null) {
builder.main(application.getMainApplicationClass());
}
if (environment.getPropertySources().contains("refreshArgs")) {
builderApplication.setListeners(this.filterListeners(builderApplication.getListeners()));
}
builder.sources(new Class[]{BootstrapImportSelectorConfiguration.class});
ConfigurableApplicationContext context = builder.run(new String[0]);
context.setId("bootstrap");
this.addAncestorInitializer(application, context);
bootstrapProperties.remove("bootstrap");
this.mergeDefaultProperties(environment.getPropertySources(), bootstrapProperties);
return context;
}
监控到尝试加载资源文件:
**加载 bootstrap 文件**
file:./config/bootstrap.[properties|xml|yml|yaml]
file:./bootstrap.[properties|xml|yml|yaml]
classpath:/config/bootstrap.[properties|xml|yml|yaml]
classpath:/bootstrap.[properties|xml|yml|yaml]
**加载 bootstrap-composite 文件**
file:./config/bootstrap-composite.[properties|xml|yml|yaml]
file:./bootstrap-composite.[properties|xml|yml|yaml]
classpath:/config/bootstrap-composite.[properties|xml|yml|yaml]
classpath:/bootstrap-composite.[properties|xml|yml|yaml]
3)第一次SpringApplication#run()执行到SpringAppllication#prepareEnvironment(…)执行过程中加载在资源文件:
第一次SpringApplication#run执行过程中,SpringApplication#prepareEnvironment(…)执行过程中加载在资源文件:
application.yaml...
file:./config/application.[properties|xml|yml|yaml]
file:./application.[properties|xml|yml|yaml]
classpath:/config/application.[properties|xml|yml|yaml]
classpath:/application.[properties|xml|yml|yaml]
file:./config/application-composite.[properties|xml|yml|yaml]
file:./application-composite.[properties|xml|yml|yaml]
classpath:/config/application-composite.[properties|xml|yml|yaml]
classpath:/application-composite.[properties|xml|yml|yaml]
4)第一次SpringApplication#run()执行到SpringApplication#prepareContext(…)执行第三次SpringApplication#run()
代码执行SpringApplication#prepareContext(…)
args = {String[4]@5280}
0 = “–spring.config.name=application”
1 = “–spring.cloud.bootstrap.enabled=false”
2 = “–encrypt.failOnError=false”3 = “–spring.config.location=classpath:/config/uat/”
监控到尝试加载资源文件:
**加载 application 文件**
classpath:/config/uat/application-default.[properties|xml|yml|yaml]
5)第一次SpringApplication#run()执行完,返回context
org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@784c5ef5, started on Tue Mar 13 11:16:25 CST 2021, parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@7876d598
bootstrap.yml、application.yml、application-dev.yml配置文件之间覆盖性验证:
1)如果三个文件都配置了server.port,后加载的配置覆盖前者
加载顺序:bootstrap.yml->application.yml->applicaiton-dev.yml
2)如果是nacos的配置中心,必须配置到boostrap.yml
如果是bootstrap.yml、application.yml、application-dev.yml都配置了spring.cloud.nacos.config,那么是boostrap.yml中生效。
如果是bootstrap.yml中未配置,其他两个文件配置了,也不生效。spring.cloud.nacos.config采用默认值。
Original: https://www.cnblogs.com/yy3b2007com/p/14531956.html
Author: cctext
Title: SpringBoot(十九):SpringBoot运行启动时执行3次SpringApplication#run(args)加载了哪些配置文件?以及配置文件之间的覆盖性。
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/540991/
转载文章受原作者版权保护。转载请注明原作者出处!