springboot加载配值文件的实现步骤

 更新时间:2025年03月07日 12:01:16   作者:花花进修  
本文主要介绍了springboot加载配值文件的实现步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

Spring Boot 加载配置文件的机制是其核心功能之一,它通过一系列源码实现从不同来源加载配置,并支持灵活的配置管理。以下是 Spring Boot 加载配置文件的源码解析及其实现原理的详细说明。(下述两段是加载配置文件的源码片段) 

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
        this.sources = new LinkedHashSet();
        this.bannerMode = Mode.CONSOLE;
        this.logStartupInfo = true;
        this.addCommandLineProperties = true;
        this.addConversionService = true;
        this.headless = true;

        this.registerShutdownHook = true;
        this.additionalProfiles = Collections.emptySet();
        this.isCustomEnvironment = false;
        this.lazyInitialization = false;
        this.applicationContextFactory = ApplicationContextFactory.DEFAULT;
        this.applicationStartup = ApplicationStartup.DEFAULT;

        this.resourceLoader = resourceLoader;
        Assert.notNull(primarySources, "PrimarySources must not be null");
        this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
        //1.推测web应用类型(NONE   REACTIVE   SERVLET)
        this.webApplicationType = WebApplicationType.deduceFromClasspath();

         //2.从spring.factories中获取BootstrapRegistryInitializer对象
        this.bootstrapRegistryInitializers =             
       this.getBootstrapRegistryInitializersFromSpringFactories();
        
 //3.从spring.factories中获取ApplicationContextInitializer对象
 this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
         //4.从spring.factories中获取ApplicationListener对象
        this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
        //5.推测出Main类 (main()方法所在的类)
        this.mainApplicationClass = this.deduceMainApplicationClass();
    }
public ConfigurableApplicationContext run(String... args) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        DefaultBootstrapContext bootstrapContext = this.createBootstrapContext();
        ConfigurableApplicationContext context = null;
        this.configureHeadlessProperty();
           /**从spring.factories中获取SpringApplicationRunListeners 对象
            * 默认会拿到一个EventPublishingRunListener ,他会启动过程的各个阶段发布对应的事件
            **/
        SpringApplicationRunListeners listeners = this.getRunListeners(args);
        listeners.starting(bootstrapContext, this.mainApplicationClass);

        try {
            //将run()的参数封装为DefaultApplicationArguments对象
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
                //配置文件的入口
            ConfigurableEnvironment environment = this.prepareEnvironment(listeners, bootstrapContext, applicationArguments);
            this.configureIgnoreBeanInfo(environment);
            Banner printedBanner = this.printBanner(environment);
            //根据应用类型创建Spring容器
            context = this.createApplicationContext();
            context.setApplicationStartup(this.applicationStartup);
            this.prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
               //刷新Spring容器, 会解析配置类  扫描  启动Webserver
            this.refreshContext(context);
            this.afterRefresh(context, applicationArguments);
            stopWatch.stop();
            if (this.logStartupInfo) {
                (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
            }

            listeners.started(context);

            //调用applicationArguments 和CommandLineRunner
            this.callRunners(context, applicationArguments);
        } catch (Throwable var10) {
            this.handleRunFailure(context, var10, listeners);
            throw new IllegalStateException(var10);
        }

        try {
            listeners.running(context);
            return context;
        } catch (Throwable var9) {
            this.handleRunFailure(context, var9, (SpringApplicationRunListeners)null);
            throw new IllegalStateException(var9);
        }
    }

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

public ConfigurableApplicationContext run(String... args) {
    // ...
    ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
    // ...
}

说明:

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

2.2 prepareEnvironment()

prepareEnvironment() 方法会调用 configureEnvironment() 来加载配置文件。

源码位置:org.springframework.boot.SpringApplication

private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments) {
    // 创建 Environment 对象
    ConfigurableEnvironment environment = getOrCreateEnvironment();
    // 配置 Environment,加载配置文件
    configureEnvironment(environment, applicationArguments.getSourceArgs());
    // 触发环境准备事件
    listeners.environmentPrepared(environment);
    // 将 Environment 绑定到 SpringApplication
    bindToSpringApplication(environment);
    return environment;
}

说明:

  • getOrCreateEnvironment():根据应用类型(Web 或非 Web)创建 StandardEnvironment 或 StandardServletEnvironment

  • configureEnvironment():加载配置文件和其他外部化配置。

2.3 configureEnvironment()

configureEnvironment() 方法会调用 configurePropertySources() 和 configureProfiles() 来加载配置文件和激活 Profile。

源码位置:org.springframework.boot.SpringApplication

protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
    configurePropertySources(environment, args);
    configureProfiles(environment, args);
}

说明:

  • configurePropertySources():加载命令行参数、默认配置文件等。

  • configureProfiles():设置激活的 Profile。

2.4 ConfigFileApplicationListener

ConfigFileApplicationListener 是 Spring Boot 加载配置文件的核心类。它监听 ApplicationEnvironmentPreparedEvent 事件,并加载 application.properties 或 application.yml 文件。

源码位置:org.springframework.boot.context.config.ConfigFileApplicationListener

public void onApplicationEvent(ApplicationEvent event) {
    if (event instanceof ApplicationEnvironmentPreparedEvent) {
        onApplicationEnvironmentPreparedEvent((ApplicationEnvironmentPreparedEvent) event);
    }
}

说明:

onApplicationEnvironmentPreparedEvent():在环境准备完成后触发,加载配置文件。

2.5 Loader.load()

Loader 是 ConfigFileApplicationListener 的内部类,负责实际加载配置文件。

源码位置:org.springframework.boot.context.config.ConfigFileApplicationListener.Loader

void load() {
    for (String location : getSearchLocations()) {
        for (String name : getSearchNames()) {
            load(location, name);
        }
    }
}

说明:

  • getSearchLocations():获取配置文件的搜索路径(如 classpath:/file:./config/ 等)。

  • getSearchNames():获取配置文件的名称(如 application)。

  • load(location, name):从指定路径加载配置文件。

2.6 PropertySourcesLoader

PropertySourcesLoader 负责将配置文件内容加载到 PropertySource 中。

源码位置:org.springframework.boot.env.PropertySourcesLoader

public PropertySource<?> load(Resource resource) throws IOException {
    if (resource.getFilename().endsWith(".yml")) {
        return loadYaml(resource);
    } else {
        return loadProperties(resource);
    }
}

说明:

  • loadYaml():加载 YAML 格式的配置文件。

  • loadProperties():加载 Properties 格式的配置文件。

2.7 Profile 的加载

Spring Boot 支持通过 Profile 加载不同的配置文件。Profiles 和 ProfilePropertySource 负责处理 Profile 相关的配置。

源码位置:org.springframework.core.env.Profiles

public static Profiles of(String... profiles) {
    return new Profiles() {
        @Override
        public boolean matches(Predicate<String> predicate) {
            // ...
        }
    };
}

说明:

  • Profiles:管理 Profile 的激活状态。

  • ProfilePropertySource:根据激活的 Profile 加载特定的配置文件。

3.Spring Boot配置文件的实现原理

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

  • 多来源加载:支持从类路径、外部目录、环境变量、命令行参数等多种来源加载配置。
  • 优先级机制:后加载的配置会覆盖先加载的配置,命令行参数的优先级最高。
  • Profile 支持:通过 spring.profiles.active 指定激活的 Profile,加载对应的配置文件。
  • 外部化配置:支持从外部文件、环境变量、JNDI 等加载配置,适用于云原生和容器化部署。

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

以下是一个完整的示例,展示 Spring Boot 如何加载配置文件。

4.1 默认配置文件

application.properties:

server.port=8080
spring.profiles.active=dev

4.2 Profile 特定的配置文件

application-dev.properties:

server.port=8081

4.3 Java 代码

@RestController
public class MyController {
​
    @Value("${server.port}")
    private String port;
​
    @GetMapping("/port")
    public String getPort() {
        return "Server port: " + port;
    }
}

4.4 运行结果

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

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

5. 总结

Spring Boot 加载配置文件的机制非常灵活,支持多来源、多格式的配置加载。通过 EnvironmentPropertySourceConfigFileApplicationListener 等核心类和组件,Spring Boot 实现了配置文件的加载、合并和优先级管理。理解这些源码和机制,可以帮助我们更好地使用和扩展 Spring Boot 的配置功能。

到此这篇关于springboot加载配值文件的实现步骤的文章就介绍到这了,更多相关springboot加载配值文件内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Spring Boot中的那些条件判断的实现方法

    Spring Boot中的那些条件判断的实现方法

    这篇文章主要介绍了Spring Boot中的那些条件判断的实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-04-04
  • SpringCloud链路追踪组件Sleuth配置方法解析

    SpringCloud链路追踪组件Sleuth配置方法解析

    这篇文章主要介绍了SpringCloud链路追踪组件Sleuth配置方法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-03-03
  • Java用邻接表存储图的示例代码

    Java用邻接表存储图的示例代码

    邻接表是图的一种链式存储方法,其数据结构包括两部分:节点和邻接点。本文将用邻接表实现存储图,感兴趣的小伙伴可以了解一下
    2022-06-06
  • java 两阶段终止线程的正确做法

    java 两阶段终止线程的正确做法

    这篇文章主要给大家分享了java 两阶段终止线程的正确做法,文章列举出错误的做法与正确做法做对比,具有一定的参考价值,需要的小伙伴可以参考一下,希望对你有所帮助
    2021-12-12
  • Java结合redistemplate使用分布式锁案例讲解

    Java结合redistemplate使用分布式锁案例讲解

    在Java中使用RedisTemplate结合Redis来实现分布式锁是一种常见的做法,特别适用于微服务架构或多实例部署的应用程序中,以确保数据的一致性和避免竞态条件,下面给大家分享使用Spring Boot和RedisTemplate实现分布式锁的案例,感兴趣的朋友一起看看吧
    2024-08-08
  • Mybatis Lombok使用方法与复杂查询介绍

    Mybatis Lombok使用方法与复杂查询介绍

    Lombok是一种Java实用工具,可用来帮助开发人员消除Java的冗长,尤其是对于简单的Java对象(POJO),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
    2022-10-10
  • Spring  ApplicationContextAware 接口的作用及使用方式

    Spring  ApplicationContextAware 接口的作用及使用方式

    Spring提供了许多回调接口,用于Bean生命周期中执行特定的操作,通过实现ApplicationContextAware接口,Spring提供了一种便捷的方式让 Bean获取对Spring容器的引用,本文介绍ApplicationContextAware接口的作用、使用方式,以及在实际应用中的常见场景,感兴趣的朋友一起看看吧
    2024-01-01
  • IntelliJ IDEA 代码运行时中文出现乱码问题及解决方法

    IntelliJ IDEA 代码运行时中文出现乱码问题及解决方法

    在我们刚接触到IDEA时,想美滋滋的敲一个“hello world”来问候这个世界,但难免会遇到这种问题乱码,这篇文章主要介绍了解决IntelliJ IDEA 代码运行时中文出现乱码问题,需要的朋友可以参考下
    2023-09-09
  • Java两整数相除向上取整的方式详解(Math.ceil())

    Java两整数相除向上取整的方式详解(Math.ceil())

    在调外部接口获取列表数据时,需要判断是否已经取完了所有的值,因此需要用到向上取整,下面这篇文章主要给大家介绍了关于Java两整数相除向上取整的相关资料,需要的朋友可以参考下
    2022-06-06
  • Java参数按值传递示例演示

    Java参数按值传递示例演示

    在Java中,方法参数的传递方式实际上是按值传递,接下来通过本文给大家介绍了Java参数按值传递示例演示,需要的朋友可以参考下
    2023-09-09

最新评论