spring boot 是怎样加载配值文件的

[复制链接]
发表于 2025-10-21 02:28:00 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
  1. public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
  2.         this.sources = new LinkedHashSet();
  3.         this.bannerMode = Mode.CONSOLE;
  4.         this.logStartupInfo = true;
  5.         this.addCommandLineProperties = true;
  6.         this.addConversionService = true;
  7.         this.headless = true;
  8.         this.registerShutdownHook = true;
  9.         this.additionalProfiles = Collections.emptySet();
  10.         this.isCustomEnvironment = false;
  11.         this.lazyInitialization = false;
  12.         this.applicationContextFactory = ApplicationContextFactory.DEFAULT;
  13.         this.applicationStartup = ApplicationStartup.DEFAULT;
  14.         this.resourceLoader = resourceLoader;
  15.         Assert.notNull(primarySources, "PrimarySources must not be null");
  16.         this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
  17.         //1.推测web应用类型(NONE   REACTIVE   SERVLET)
  18.         this.webApplicationType = WebApplicationType.deduceFromClasspath();
  19.          //2.从spring.factories中获取BootstrapRegistryInitializer对象
  20.         this.bootstrapRegistryInitializers =            
  21.        this.getBootstrapRegistryInitializersFromSpringFactories();
  22.         
  23. //3.从spring.factories中获取ApplicationContextInitializer对象
  24. this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
  25.          //4.从spring.factories中获取ApplicationListener对象
  26.         this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
  27.         //5.推测出Main类 (main()方法所在的类)
  28.         this.mainApplicationClass = this.deduceMainApplicationClass();
  29.     }
复制代码
  1. public ConfigurableApplicationContext run(String... args) {
  2.         StopWatch stopWatch = new StopWatch();
  3.         stopWatch.start();
  4.         DefaultBootstrapContext bootstrapContext = this.createBootstrapContext();
  5.         ConfigurableApplicationContext context = null;
  6.         this.configureHeadlessProperty();
  7.            /**从spring.factories中获取SpringApplicationRunListeners 对象
  8.             * 默认会拿到一个EventPublishingRunListener ,他会启动过程的各个阶段发布对应的事件
  9.             **/
  10.         SpringApplicationRunListeners listeners = this.getRunListeners(args);
  11.         listeners.starting(bootstrapContext, this.mainApplicationClass);
  12.         try {
  13.             //将run()的参数封装为DefaultApplicationArguments对象
  14.             ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
  15.                 //配置文件的入口
  16.             ConfigurableEnvironment environment = this.prepareEnvironment(listeners, bootstrapContext, applicationArguments);
  17.             this.configureIgnoreBeanInfo(environment);
  18.             Banner printedBanner = this.printBanner(environment);
  19.             //根据应用类型创建Spring容器
  20.             context = this.createApplicationContext();
  21.             context.setApplicationStartup(this.applicationStartup);
  22.             this.prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
  23.                //刷新Spring容器, 会解析配置类  扫描  启动Webserver
  24.             this.refreshContext(context);
  25.             this.afterRefresh(context, applicationArguments);
  26.             stopWatch.stop();
  27.             if (this.logStartupInfo) {
  28.                 (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
  29.             }
  30.             listeners.started(context);
  31.             //调用applicationArguments 和CommandLineRunner
  32.             this.callRunners(context, applicationArguments);
  33.         } catch (Throwable var10) {
  34.             this.handleRunFailure(context, var10, listeners);
  35.             throw new IllegalStateException(var10);
  36.         }
  37.         try {
  38.             listeners.running(context);
  39.             return context;
  40.         } catch (Throwable var9) {
  41.             this.handleRunFailure(context, var9, (SpringApplicationRunListeners)null);
  42.             throw new IllegalStateException(var9);
  43.         }
  44.     }
复制代码
Spring Boot 加载设置文件的机制是其核心功能之一,它通过一系列源码实现从差别泉源加载设置,并支持机动的设置管理。以下是 Spring Boot 加载设置文件的源码分析及着实现原理的具体阐明。(上述两段是加载设置文件的源码片断)

1. Spring Boot 加载设置文件的团体流程

Spring Boot 加载设置文件的流程可以分为以下几个步调:

  •         初始化 Environment:在应用启动时,创建并初始化 Environment 对象。
  •         加载默认设置文件:从 application.properties 或 application.yml 加载设置。
  •         加载 Profile 特定的设置文件:根据激活的 Profile 加载 application-{profile}.properties 或 application-{profile}.yml。
  •         加载外部化设置:从下令行参数、情况变量、JNDI 等外部泉源加载设置。
  •         归并设置:将全部设置泉源归并到 Environment 中,供应用步伐利用。

2. 源码分析

以下是 Spring Boot 加载设置文件的核心源码分析。
2.1 SpringApplication.run()

Spring Boot 应用的启动入口是 SpringApplication.run() 方法。在这个方法中,会初始化 Environment 并加载设置文件。
源码位置:org.springframework.boot.SpringApplication
  1. public ConfigurableApplicationContext run(String... args) {
  2.    // ...
  3.    ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
  4.    // ...
  5. }
复制代码
阐明


  •         prepareEnvironment() 方法负责创建和设置 Environment 对象。

2.2 prepareEnvironment()

prepareEnvironment() 方法会调用 configureEnvironment() 来加载设置文件。
源码位置:org.springframework.boot.SpringApplication
  1. private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments) {
  2.    // 创建 Environment 对象
  3.    ConfigurableEnvironment environment = getOrCreateEnvironment();
  4.    // 配置 Environment,加载配置文件
  5.    configureEnvironment(environment, applicationArguments.getSourceArgs());
  6.    // 触发环境准备事件
  7.    listeners.environmentPrepared(environment);
  8.    // 将 Environment 绑定到 SpringApplication
  9.    bindToSpringApplication(environment);
  10.    return environment;
  11. }
复制代码
阐明


  •         getOrCreateEnvironment():根据应用范例(Web 或非 Web)创建 StandardEnvironment 或 StandardServletEnvironment。
  •         configureEnvironment():加载设置文件和其他外部化设置。

2.3 configureEnvironment()

configureEnvironment() 方法会调用 configurePropertySources() 和 configureProfiles() 来加载设置文件和激活 Profile。
源码位置:org.springframework.boot.SpringApplication
  1. protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
  2.    configurePropertySources(environment, args);
  3.    configureProfiles(environment, args);
  4. }
复制代码
阐明


  •         configurePropertySources():加载下令行参数、默认设置文件等。
  •         configureProfiles():设置激活的 Profile。

2.4 ConfigFileApplicationListener

ConfigFileApplicationListener 是 Spring Boot 加载设置文件的核心类。它监听 ApplicationEnvironmentPreparedEvent 变乱,并加载 application.properties 或 application.yml 文件。
源码位置:org.springframework.boot.context.config.ConfigFileApplicationListener
  1. public void onApplicationEvent(ApplicationEvent event) {
  2.    if (event instanceof ApplicationEnvironmentPreparedEvent) {
  3.        onApplicationEnvironmentPreparedEvent((ApplicationEnvironmentPreparedEvent) event);
  4.    }
  5. }
复制代码
阐明


  •         onApplicationEnvironmentPreparedEvent():在情况准备完成后触发,加载设置文件。

2.5 Loader.load()

Loader 是 ConfigFileApplicationListener 的内部类,负责现实加载设置文件。
源码位置:org.springframework.boot.context.config.ConfigFileApplicationListener.Loader
  1. void load() {
  2.    for (String location : getSearchLocations()) {
  3.        for (String name : getSearchNames()) {
  4.            load(location, name);
  5.        }
  6.    }
  7. }
复制代码
阐明


  •         getSearchLocations():获取设置文件的搜索路径(如 classpath:/、file:./config/ 等)。
  •         getSearchNames():获取设置文件的名称(如 application)。
  •         load(location, name):从指定路径加载设置文件。

2.6 PropertySourcesLoader

PropertySourcesLoader 负责将设置文件内容加载到 PropertySource 中。
源码位置:org.springframework.boot.env.PropertySourcesLoader
  1. public PropertySource<?> load(Resource resource) throws IOException {
  2.    if (resource.getFilename().endsWith(".yml")) {
  3.        return loadYaml(resource);
  4.    } else {
  5.        return loadProperties(resource);
  6.    }
  7. }
复制代码
阐明


  •         loadYaml():加载 YAML 格式的设置文件。
  •         loadProperties():加载 Properties 格式的设置文件。

2.7 Profile 的加载

Spring Boot 支持通过 Profile 加载差别的设置文件。Profiles 和 ProfilePropertySource 负责处理处罚 Profile 相干的设置。
源码位置:org.springframework.core.env.Profiles
  1. public static Profiles of(String... profiles) {
  2.    return new Profiles() {
  3.        @Override
  4.        public boolean matches(Predicate<String> predicate) {
  5.            // ...
  6.        }
  7.    };
  8. }
复制代码
阐明


  •         Profiles:管理 Profile 的激活状态。
  •         ProfilePropertySource:根据激活的 Profile 加载特定的设置文件。

3. Spring Boot 加载设置文件的实现原理

Spring Boot 加载设置文件的实现原理可以总结为以下几点:

  •         多泉源加载

    •                 支持从类路径、外部目次、情况变量、下令行参数等多种泉源加载设置。
           
  •         优先级机制

    •                 后加载的设置会覆盖先加载的设置,下令行参数的优先级最高。
           
  •         Profile 支持

    •                 通过 spring.profiles.active 指定激活的 Profile,加载对应的设置文件。
           
  •         外部化设置

    •                 支持从外部文件、情况变量、JNDI 等加载设置,实用于云原生容器化摆设。
           

4. 示例:Spring Boot 加载设置文件的流程

以下是一个完备的示例,展示 Spring Boot 怎样加载设置文件。
4.1 默认设置文件

application.properties:
  1. server.port=8080
  2. spring.profiles.active=dev
复制代码
4.2 Profile 特定的设置文件

application-dev.properties:
  1. server.port=8081
复制代码
4.3 Java 代码
  1. @RestController
  2. public class MyController {
  3.    @Value("${server.port}")
  4.    private String port;
  5.    @GetMapping("/port")
  6.    public String getPort() {
  7.        return "Server port: " + port;
  8.    }
  9. }
复制代码
4.4 运行效果


  •         如果激活的 Profile 是 dev,则 server.port 的值为 8081。
  •         如果没有激活 Profile,则 server.port 的值为 8080。

5. 总结

Spring Boot 加载设置文件的机制非常机动,支持多泉源、多格式的设置加载。通过 Environment、PropertySource、ConfigFileApplicationListener 等核心类和组件,Spring Boot 实现了设置文件的加载、归并和优先级管理。明白这些源码和机制,可以资助我们更好地利用和扩展 Spring Boot 的设置功能


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
继续阅读请点击广告
回复

使用道具 举报

×
登录参与点评抽奖,加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表