菜单 学习猿地 - LMONKEY

VIP

开通学习猿地VIP

尊享10项VIP特权 持续新增

知识通关挑战

打卡带练!告别无效练习

接私单赚外块

VIP优先接,累计金额超百万

学习猿地私房课免费学

大厂实战课仅对VIP开放

你的一对一导师

每月可免费咨询大牛30次

领取更多软件工程师实用特权

入驻
171
0

SpringBoot(十九):SpringBoot运行启动时执行3次SpringApplication#run(args)加载了哪些配置文件?以及配置文件之间的覆盖性。

原创
05/13 14:22
阅读数 84291

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<String, Object> 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采用默认值。

 

发表评论

0/200
171 点赞
0 评论
收藏
为你推荐 换一批