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

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

    基础才是编程人员应该深入研究的问题,比如:
    1)List/Set/Map内部组成原理|区别
    2)mysql索引存储结构&如何调优/b-tree特点、计算复杂度及影响复杂度的因素。。。
    3)JVM运行组成与原理及调优
    4)Java类加载器运行原理
    5)Java中GC过程原理|使用的回收算法原理
    6)Redis中hash一致性实现及与hash其他区别
    7)Java多线程、线程池开发、管理Lock与Synchroined区别
    8)Spring IOC/AOP 原理;加载过程的。。。
    +加关注】。

  • 相关阅读:
    创建桌面快捷方式
    令牌桶在数据通信QoS流量监管中的应用
    cocos2d-x 实现clash of clans多点聚焦缩放场景
    NotePad++ 快捷键中文说明
    2017第24周日
    《自信力~成为更好的自己》晨读笔记
    不知道如何决定的时候就快速决定
    《意外之外》晨读笔记
    《从“为什么”开始》听书笔记
    解决电脑上网问题记录
  • 原文地址:https://www.cnblogs.com/yy3b2007com/p/14531956.html
Copyright © 2011-2022 走看看