读取 SpringBoot 配置的6种方式

大家好,我是苏三~

从配置文件中获取属性应该是SpringBoot开发中最为常用的功能之一,但就是这么常用的功能,仍然有很多开发者在这个方面踩坑。

我整理了几种获取配置属性的方式,目的不仅是要让大家学会如何使用,更重要的是弄清配置加载、读取的底层原理,一旦出现问题可以分析出其症结所在,而不是一报错取不到属性,无头苍蝇般的重启项目,在句句卧槽中逐渐抓狂~

以下示例源码 Springboot 版本均为 2.7.6

下边我们一一过下这几种玩法和原理,看看有哪些是你没用过的!话不多说,开始搞~

一、Environment

使用 Environment 方式来获取配置属性值非常简单,只要注入Environment类调用其方法getProperty(属性key)即可,但知其然知其所以然,简单了解下它的原理,因为后续的几种获取配置的方法都和它息息相关。

@Slf4j
@SpringBootTest
public class EnvironmentTest {

    @Resource
    private Environment env;

    @Test
    public void var1Test() {
        String var1 = env.getProperty("env101.var1");
        log.info("Environment 配置获取 {}", var1);
    }
}

1、什么是 Environment?

Environment 是 springboot 核心的环境配置接口,它提供了简单的方法来访问应用程序属性,包括系统属性、操作系统环境变量、命令行参数、和应用程序配置文件中定义的属性等等。

2、配置初始化

Springboot 程序启动加载流程里,会执行SpringApplication.run中的prepareEnvironment()方法进行配置的初始化,那初始化过程每一步都做了什么呢?

private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
   DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
      /** 
      * 1、创建 ConfigurableEnvironment 对象:首先调用 getOrCreateEnvironment() 方法获取或创建
      * ConfigurableEnvironment 对象,该对象用于存储环境参数。如果已经存在 ConfigurableEnvironment 对象,则直接使用它;否则,根据用户的配置和默认配置创建一个新的。
      */
      ConfigurableEnvironment environment = getOrCreateEnvironment();
      /**
      * 2、解析并加载用户指定的配置文件,将其作为 PropertySource 添加到环境对象中。该方法默认会解析 application.properties 和 application.yml 文件,并将其添加到 ConfigurableEnvironment 对象中。
      * PropertySource 或 PropertySourcesPlaceholderConfigurer 加载应用程序的定制化配置。
      */
      configureEnvironment(environment, applicationArguments.getSourceArgs());
      // 3、加载所有的系统属性,并将它们添加到 ConfigurableEnvironment 对象中
      ConfigurationPropertySources.attach(environment);
      // 4、通知监听器环境参数已经准备就绪
      listeners.environmentPrepared(bootstrapContext, environment);
      /**
      *  5、将默认的属性源中的所有属性值移到环境对象的队列末尾,
      这样用户自定义的属性值就可以覆盖默认的属性值。这是为了避免用户无意中覆盖了 Spring Boot 所提供的默认属性。
      */
      DefaultPropertiesPropertySource.moveToEnd(environment);
      Assert.state(!environment.containsProperty("spring.main.environment-prefix"),
          "Environment prefix cannot be set via properties.");
      // 6、将 Spring Boot 应用程序的属性绑定到环境对象上,以便能够正确地读取和使用这些配置属性
      bindToSpringApplication(environment);
      // 7、如果没有自定义的环境类型,则使用 EnvironmentConverter 类型将环境对象转换为标准的环境类型,并添加到 ConfigurableEnvironment 对象中。
      if (!this.isCustomEnvironment) {
        EnvironmentConverter environmentConverter = new EnvironmentConverter(getClassLoader());
        environment = environmentConverter.convertEnvironmentIfNecessary(environment, deduceEnvironmentClass());
      }
      // 8、再次加载系统配置,以防止被其他配置覆盖
      ConfigurationPropertySources.attach(environment);
      return environment;
}

看看它的配置加载流程步骤:

  • 创建 环境对象 ConfigurableEnvironment 用于存储环境参数;

  • configureEnvironment 方法加载默认的 application.propertiesapplication.yml 配置文件;以及用户指定的配置文件,将其封装为 PropertySource 添加到环境对象中;

  • attach(): 加载所有的系统属性,并将它们添加到环境对象中;

  • listeners.environmentPrepared(): 发送环境参数配置已经准备就绪的监听通知;

  • moveToEnd(): 将 系统默认 的属性源中的所有属性值移到环境对象的队列末尾,这样用户自定义的属性值就可以覆盖默认的属性值。

  • bindToSpringApplication: 应用程序的属性绑定到 Bean 对象上;

  • attach(): 再次加载系统配置,以防止被其他配置覆盖;

上边的配置加载流程中,各种配置属性会封装成一个个抽象的数据结构 PropertySource中,这个数据结构代码格式如下,key-value形式。

public abstract class PropertySource<T> {
    protected final String name; // 属性源名称
    protected final T source; // 属性源值(一个泛型,比如Map,Property)
    public String getName();  // 获取属性源的名字  
    public T getSource(); // 获取属性源值  
    public boolean containsProperty(String name);  //是否包含某个属性  
    public abstract Object getProperty(String name);   //得到属性名对应的属性值   
} 

PropertySource 有诸多的实现类用于管理应用程序的配置属性。不同的 PropertySource 实现类可以从不同的来源获取配置属性,例如文件、环境变量、命令行参数等。其中涉及到的一些实现类有:

图片

关系图

  • MapPropertySource: Map 键值对的对象转换为 PropertySource 对象的适配器;

  • PropertiesPropertySource: Properties 对象中的所有配置属性转换为 Spring 环境中的属性值;

  • ResourcePropertySource: 从文件系统或者 classpath 中加载配置属性,封装成 PropertySource对象;

  • ServletConfigPropertySource: Servlet 配置中读取配置属性,封装成 PropertySource 对象;

  • ServletContextPropertySource: Servlet 上下文中读取配置属性,封装成 PropertySource 对象;

  • StubPropertySource: 是个空的实现类,它的作用仅仅是给 CompositePropertySource 类作为默认的父级属性源,以避免空指针异常;

  • CompositePropertySource: 是个复合型的实现类,内部维护了 PropertySource集合队列,可以将多个 PropertySource 对象合并;

  • SystemEnvironmentPropertySource: 操作系统环境变量中读取配置属性,封装成 PropertySource 对象;

上边各类配置初始化生成的 PropertySource 对象会被维护到集合队列中。

List<PropertySource<?>> sources = new ArrayList<PropertySource<?>>()

配置初始化完毕,应用程序上下文AbstractApplicationContext会加载配置,这样程序在运行时就可以随时获取配置信息了。

 private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,
   ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
   ApplicationArguments applicationArguments, Banner printedBanner) {
    // 应用上下文加载环境对象
  context.setEnvironment(environment);
  postProcessApplicationContext(context);
    .........
  }

3、读取配置

看明白上边配置加载的流程,其实读取配置就容易理解了,无非就是遍历队列里的PropertySource,拿属性名称name匹配对应的属性值source

PropertyResolver是获取配置的关键类,其内部提供了操作PropertySource 队列的方法,核心方法getProperty(key)获取配置值,看了下这个类的依赖关系,发现 Environment 是它子类。

图片

那么直接用 PropertyResolver 来获取配置属性其实也是可以的,到这我们就大致明白了 Springboot 配置的加载和读取了。

@Slf4j
@SpringBootTest
public class EnvironmentTest {

    @Resource
    private PropertyResolver env;
    
    @Test
    public void var1Test() {
        String var1 = env.getProperty("env101.var1");
        log.info("Environment 配置获取 {}", var1);
    }
}

二、@Value 注解

@Value注解是Spring框架提供的用于注入配置属性值的注解,它可用于类的成员变量方法参数构造函数参数上,这个记住很重要!

在应用程序启动时,使用 @Value 注解的 Bean 会被实例化。所有使用了 @Value 注解的 Bean 会被加入到 PropertySourcesPlaceholderConfigurer 的后置处理器集合中。

当后置处理器开始执行时,它会读取 Bean 中所有 @Value 注解所标注的值,并通过反射将解析后的属性值赋值给标有 @Value 注解的成员变量、方法参数和构造函数参数。

需要注意,在使用 @Value 注解时需要确保注入的属性值已经加载到 Spring 容器中,否则会导致注入失败。

如何使用

src/main/resources目录下的application.yml配置文件中添加env101.var1属性。

env101:
  var1: var1-公众号:程序员小富

只要在变量上加注解 @Value("${env101.var1}")就可以了,@Value 注解会自动将配置文件中的env101.var1属性值注入到var1字段中,跑个单元测试看一下结果。

@Slf4j
@SpringBootTest
public class EnvVariablesTest {

    @Value("${env101.var1}")
    private String var1;
    
    @Test
    public void var1Test(){
        log.info("配置文件属性: {}",var1);
    }
}

毫无悬念,成功拿到配置数据。

图片

虽然@Value注解方式使用起来很简单,如果使用不当还会遇到不少坑。

1、缺失配置

如果在代码中引用变量,配置文件中未进行配值,就会出现类似下图所示的错误。

图片

为了避免此类错误导致服务启动异常,我们可以在引用变量的同时给它赋一个默认值,以确保即使在未正确配值的情况下,程序依然能够正常运行。

@Value("${env101.var1:我是小富}")
private String var1;

2、静态变量(static)赋值

还有一种常见的使用误区,就是将 @Value 注解加到静态变量上,这样做是无法获取属性值的。静态变量是类的属性,并不属于对象的属性,而 Spring是基于对象的属性进行依赖注入的,类在应用启动时静态变量就被初始化,此时 Bean还未被实例化,因此不可能通过 @Value 注入属性值。

@Slf4j
@SpringBootTest
public class EnvVariablesTest {

    @Value("${env101.var1}")
    private static String var1;
    
    @Test
    public void var1Test(){
        log.info("配置文件属性: {}",var1);
    }
}

即使 @Value 注解无法直接用在静态变量上,我们仍然可以通过获取已有 Bean实例化后的属性值,再将其赋值给静态变量来实现给静态变量赋值。

我们可以先通过 @Value 注解将属性值注入到普通 Bean中,然后在获取该 Bean对应的属性值,并将其赋值给静态变量。这样,就可以在静态变量中使用该属性值了。

@Slf4j
@SpringBootTest
public class EnvVariablesTest {

    private static String var3;
    
    private static String var4;
    
    @Value("${env101.var3}")
    public void setVar3(String var3) {
        var3 = var3;
    }
    
    EnvVariablesTest(@Value("${env101.var4}") String var4){
        var4 = var4;
    }
    
    public static String getVar4() {
        return var4;
    }

    public static String getVar3() {
        return var3;
    }
}

3、常量(final)赋值

@Value 注解加到final关键字上同样也无法获取属性值,因为 final 变量必须在构造方法中进行初始化,并且一旦被赋值便不能再次更改。而 @Value 注解是在 bean 实例化之后才进行属性注入的,因此无法在构造方法中初始化 final 变量。

@Slf4j
@SpringBootTest
public class EnvVariables2Test {

    private final String var6;

    @Autowired
    EnvVariables2Test( @Value("${env101.var6}")  String var6) {

        this.var6 = var6;
    }

    /**
     * @value注解 final 获取
     */
    @Test
    public void var1Test() {
        log.info("final 注入: {}", var6);
    }
}

4、非注册的类中使用

只有标注了@Component@Service@Controller@Repository@Configuration容器管理注解的类,由 Spring 管理的 bean 中使用 @Value注解才会生效。而对于普通的POJO类,则无法使用 @Value注解进行属性注入。

/**
 * @value注解 非注册的类中使用
 * `@Component`、`@Service`、`@Controller`、`@Repository` 或 `@Configuration` 等
 * 容器管理注解的类中使用 @Value注解才会生效
 */
@Data
@Slf4j
@Component
public class TestService {

    @Value("${env101.var7}")
    private String var7;

    public String getVar7(){
       return this.var7;
    }
}

5、引用方式不对

如果我们想要获取 TestService 类中的某个变量的属性值,需要使用依赖注入的方式,而不能使用 new 的方式。通过依赖注入的方式创建 TestService 对象,Spring 会在创建对象时将对象所需的属性值注入到其中。

  /**
   * @value注解 引用方式不对
   */
  @Test
  public void var7_1Test() {

      TestService testService = new TestService();
      log.info("引用方式不对 注入: {}", testService.getVar7());
  }

最后总结一下 @Value注解要在 Bean的生命周期内使用才能生效。

三、@ConfigurationProperties 注解

@ConfigurationProperties注解是 SpringBoot 提供的一种更加便捷来处理配置文件中的属性值的方式,可以通过自动绑定和类型转换等机制,将指定前缀的属性集合自动绑定到一个Bean对象上。

加载原理

在 Springboot 启动流程加载配置的 prepareEnvironment() 方法中,有一个重要的步骤方法 bindToSpringApplication(environment),它的作用是将配置文件中的属性值绑定到被 @ConfigurationProperties 注解标记的 Bean对象中。但此时这些对象还没有被 Spring 容器管理,因此无法完成属性的自动注入。

那么这些Bean对象又是什么时候被注册到 Spring 容器中的呢?

这就涉及到了 ConfigurationPropertiesBindingPostProcessor 类,它是 Bean后置处理器,负责扫描容器中所有被 @ConfigurationProperties 注解所标记的 Bean对象。如果找到了,则会使用 Binder 组件将外部属性的值绑定到它们身上,从而实现自动注入。

图片

  • bindToSpringApplication 主要是将属性值绑定到 Bean 对象中;

  • ConfigurationPropertiesBindingPostProcessor 负责在 Spring 容器启动时将被注解标记的 Bean 对象注册到容器中,并完成后续的属性注入操作;

如何使用

演示使用 @ConfigurationProperties 注解,在 application.yml 配置文件中添加配置项:

env101:
  var1: var1-公众号:程序员小富
  var2: var2-公众号:程序员小富

创建一个 MyConf 类用于承载所有前缀为env101的配置属性。

@Data
@Configuration
@ConfigurationProperties(prefix = "env101")
public class MyConf {

    private String var1;
    
    private String var2;
}

在需要使用var1var2属性值的地方,将 MyConf 对象注入到依赖对象中即可。

@Slf4j
@SpringBootTest
public class ConfTest {

    @Resource
    private MyConf myConf;

    @Test
    public void myConfTest() {
        log.info("@ConfigurationProperties注解 配置获取 {}", JSON.toJSONString(myConf));
    }
}

四、@PropertySources 注解

除了系统默认的 application.yml 或者 application.properties 文件外,我们还可能需要使用自定义的配置文件来实现更加灵活和个性化的配置。与默认的配置文件不同的是,自定义的配置文件无法被应用自动加载,需要我们手动指定加载。

@PropertySources 注解的实现原理相对简单,应用程序启动时扫描所有被该注解标注的类,获取到注解中指定自定义配置文件的路径,将指定路径下的配置文件内容加载到 Environment 中,这样可以通过 @Value 注解或 Environment.getProperty() 方法来获取其中定义的属性值了。

如何使用

在 src/main/resources/ 目录下创建自定义配置文件 xiaofu.properties,增加两个属性。

env101.var9=var9-程序员小富
env101.var10=var10-程序员小富

在需要使用自定义配置文件的类上添加 @PropertySources 注解,注解 value属性中指定自定义配置文件的路径,可以指定多个路径,用逗号隔开。

@Data
@Configuration
@PropertySources({
        @PropertySource(value = "classpath:xiaofu.properties",encoding = "utf-8"),
        @PropertySource(value = "classpath:xiaofu.properties",encoding = "utf-8")
})
public class PropertySourcesConf {

    @Value("${env101.var10}")
    private String var10;

    @Value("${env101.var9}")
    private String var9;
}

成功获取配置了

图片

但是当我试图加载.yaml文件时,启动项目居然报错了,经过一番摸索我发现,@PropertySources 注解只内置了PropertySourceFactory适配器。也就是说它只能加载.properties文件。

图片

那如果我想要加载一个.yaml类型文件,则需要自行实现yaml的适配器 YamlPropertySourceFactory

public class YamlPropertySourceFactory implements PropertySourceFactory {

    @Override
    public PropertySource<?> createPropertySource(String name, EncodedResource encodedResource) throws IOException {
        YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
        factory.setResources(encodedResource.getResource());

        Properties properties = factory.getObject();

        return new PropertiesPropertySource(encodedResource.getResource().getFilename(), properties);
    }
}

而在加载配置时要显示的指定使用 YamlPropertySourceFactory适配器,这样就完成了@PropertySource注解加载 yaml 文件。

@Data
@Configuration
@PropertySources({
        @PropertySource(value = "classpath:xiaofu.yaml", encoding = "utf-8", factory = YamlPropertySourceFactory.class)
})
public class PropertySourcesConf2 {

    @Value("${env101.var10}")
    private String var10;

    @Value("${env101.var9}")
    private String var9;
}

五、YamlPropertiesFactoryBean 加载 YAML 文件

我们可以使用 YamlPropertiesFactoryBean 类将 YAML 配置文件中的属性值注入到 Bean 中。

@Configuration
public class MyYamlConfig {

    @Bean
    public static PropertySourcesPlaceholderConfigurer yamlConfigurer() {
        PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
        YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();
        yaml.setResources(new ClassPathResource("xiaofu.yml"));
        configurer.setProperties(Objects.requireNonNull(yaml.getObject()));
        return configurer;
    }
}

可以通过 @Value 注解或 Environment.getProperty() 方法来获取其中定义的属性值。

@Slf4j
@SpringBootTest
public class YamlTest {

    @Value("${env101.var11}")
    private String var11;

    @Test
    public void  myYamlTest() {
        log.info("Yaml 配置获取 {}", var11);
    }
}

六、自定义读取

如果上边的几种读取配置的方式你都不喜欢,就想自己写个更流批的轮子,那也很好办。我们直接注入PropertySources获取所有属性的配置队列,你是想用注解实现还是其他什么方式,就可以为所欲为了。

@Slf4j
@SpringBootTest
public class CustomTest {

    @Autowired
    private PropertySources propertySources;

    @Test
    public void customTest() {
        for (PropertySource<?> propertySource : propertySources) {
            log.info("自定义获取 配置获取 name {} ,{}", propertySource.getName(), propertySource.getSource());
        }
    }
}

总结

我们可以通过 @Value 注解、Environment 类、@ConfigurationProperties 注解、@PropertySource 注解等方式来获取配置信息。

其中,@Value 注解适用于单个值的注入,而其他几种方式适用于批量配置的注入。不同的方式在效率、灵活性、易用性等方面存在差异,在选择配置获取方式时,还需要考虑个人编程习惯和业务需求。

如果重视代码的可读性和可维护性,则可以选择使用 @ConfigurationProperties 注解;如果更注重运行效率,则可以选择使用 Environment 类。总之,不同的场景需要选择不同的方式,以达到最优的效果。

<think>嗯,用户想要了解Spring Boot中读取配置文件的10种方法,并且需要示例代码。我需要先回顾一下自己知道的读取配置方式,然后看看是否能够凑齐十种。首先,Spring Boot常见的读取配置的方法有很多,比如使用@Value注解、Environment对象、@ConfigurationProperties,还有自定义配置文件、Profile相关配置、命令行参数、环境变量、@PropertySource注解、配置类结合@Bean,以及Spring Cloud的配置中心。不过用户可能不需要Spring Cloud的部分,但为了凑数可能可以算上。另外,还有通过编程方式加载配置文件,比如使用PropertySourcesPlaceholderConfigurer或者ResourceLoader来读取外部文件。还有可能通过YamlPropertiesFactoryBean来解析YAML文件。不过需要确认这些是否属于Spring Boot的常用方法。 接下来,我需要确保每种方法都有对应的示例代码,并且步骤清晰。比如,@Value是最基础的,直接注入值。Environment对象通过getProperty方法获取。@ConfigurationProperties用于绑定配置到对象。自定义配置文件可能需要@PropertySource来指定。Profile的话,可以通过application-{profile}.properties来区分环境。命令行参数和环境变量是外部配置方式。@PropertySource注解可以加载其他配置文件。配置类中使用@Bean结合@Value也是一种方式。另外,可能还有通过SpringApplication.setDefaultProperties设置默认属性,或者使用WebServerInitializedCustomizer获取服务器端口。不过这些是否算作不同的方法呢? 还需要注意用户提到的引用内容,虽然引用1、2、3提到了默认配置文件、自定义配置、顺序读取等,但用户现在需要的是10种方法,可能需要更全面的覆盖。比如,除了默认的application.properties,还有YAML格式的支持,以及多文档块的YAML特性。此外,还有使用Spring的ResourceUtils读取文件系统中的配置文件,或者使用@ImportResource导入XML配置,不过后者可能不太常见。还有可能通过Spring Boot的配置树(ConfigTree)用于Kubernetes环境下的配置。另外,使用第三方库如Apache Commons Configuration,但可能在Spring Boot项目中不推荐。 然后,示例代码要准确,比如@Value的使用,@ConfigurationProperties的类需要加上@Component或者通过@EnableConfigurationProperties启用。自定义配置文件需要@PropertySource和@Configuration配合。对于Profile,要展示如何切换激活的环境。命令行参数在启动时指定,环境变量在系统或容器中设置。YamlPropertiesFactoryBean的例子可能需要手动加载和解析YAML文件。另外,使用EnvironmentPostProcessor来动态加载配置,不过这可能属于高级用法,是否算作一种方法? 还需要检查是否有遗漏的方法,比如使用Spring Boot的Binder类来绑定配置,或者通过ApplicationContextInitializer来初始化配置。不过这些可能属于更底层的操作,用户可能更关注常用的方法。现在需要列出十种方法,可能需要包括: 1. @Value注解 2. Environment接口 3. @ConfigurationProperties绑定 4. 自定义配置文件(@PropertySource) 5. 多环境配置(Profile) 6. 命令行参数 7. 环境变量 8. @PropertySource加载外部配置 9. 配置类中使用@Bean和@Value 10. YamlPropertiesFactoryBean解析YAML 11. Spring Cloud Config(如果需要凑数) 12. 使用ResourceLoader读取文件 13. 使用PropertySourcesPlaceholderConfigurer 可能需要筛选出最常用的十种,排除不太常见的。比如,前九种加上命令行和环境变量可能算两种不同的外部配置方式,或者合并为外部配置来源。可能需要重新组织,确保每种方法都是独立的。例如: 1. @Value注解 2. Environment接口 3. @ConfigurationProperties绑定对象 4. @PropertySource加载自定义配置文件 5. 多环境Profile配置 6. 命令行参数 7. 环境变量 8. YAML文件配置 9. 使用Spring Boot的配置树(Volume挂载) 10. 动态配置(如数据库或远程配置) 不过需要确认每种是否有示例代码支持。比如配置树可能需要特定的目录结构,示例代码可能较复杂。而动态配置可能超出基本的读取方式。可能需要调整,确保十种都是实际可行且有代码示例的。 再检查是否有重复,比如命令行参数和环境变量都是外部配置,但属于不同的来源。YAML和Properties文件是格式不同,但都属于默认配置,可能需要分开。或者将YAML和Properties视为同一类,不过用户可能知道这两种格式,所以不需要单独作为方法。可能需要更细致的分类。 现在,整理出十种方法: 1. @Value注解注入单个属性 2. 使用Environment对象获取属性 3. @ConfigurationProperties绑定配置到Bean 4. @PropertySource加载自定义properties文件 5. 多环境配置(Profile)使用application-{profile}.properties 6. 命令行参数传递配置 7. 环境变量设置配置 8. 使用YAML格式的配置文件 9. 使用@ImportResource导入XML配置 10. 编程方式读取外部配置文件(如ResourceLoader) 不过第8点YAML可能不算一种独立的方法,因为读取方式与properties类似。第9点可能不常用。可能需要替换为使用配置类动态加载,或者使用Spring Boot的配置数据API。 或者替换为通过Spring Boot的配置顺序中的特定位置,比如加载config目录下的文件,但这也属于默认配置的一部分。或者使用SpringApplication.setDefaultProperties。 可能需要再思考,确保十种方法都是有效的且有不同的实现方式。例如: 1. @Value 2. Environment 3. @ConfigurationProperties 4. @PropertySource + 自定义properties 5. Profile多环境 6. 命令行参数 7. 环境变量 8. 外部化配置(如config/目录) 9. 使用YAML多文档块 10. 使用PropertySourcesPlaceholderConfigurer 不过外部化配置可能属于默认配置的一部分,而YAML多文档块是YAML的特性,不算独立方法。可能需要另一种方式,比如使用Spring Cloud Config,但用户可能没有使用Spring Cloud。或者使用数据库存储配置,但这需要自定义实现,不算Spring Boot内置方法。 最终,可能需要列出以下十种方式: 1. @Value注解 2. Environment接口 3. @ConfigurationProperties绑定 4. @PropertySource加载自定义properties 5. 多环境Profile配置 6. 命令行参数 7. 环境变量 8. YAML配置文件 9. 使用ResourceLoader读取外部文件 10. 配置数据API(Spring Boot 2.4+的spring.config.import) 不过第10点可能需要更详细的说明。或者替换为使用Spring Boot的Binder工具。 现在需要为每种方法编写示例代码,并确保语法正确。例如,@Value的代码片段,@ConfigurationProperties的类定义,@PropertySource的使用等。同时,注意用户提到的需要行内公式用$...$,独立公式用$$...$$,但在这个问题中可能不太涉及数学公式,所以可能不需要。但需要确保LaTeX语法正确,不过代码示例应放在代码块中。 最后,生成相关问题,比如性能分析、配置优先级、最佳实践等。</think>在 Spring Boot 中读取配置文件的 10 种方式及示例代码整理如下: --- ### 1. **`@Value` 注解注入单个属性** 直接注入单个配置值: ```java @RestController public class DemoController { @Value("${app.name}") private String appName; @GetMapping("/info") public String getInfo() { return appName; } } ``` 配置文件中需定义 `app.name=MyApplication`[^3]。 --- ### 2. **`Environment` 接口动态获取属性** 通过 `Environment` 对象读取配置: ```java @Autowired private Environment env; public void printConfig() { String port = env.getProperty("server.port"); System.out.println("端口号:" + port); } ``` --- ### 3. **`@ConfigurationProperties` 绑定配置到对象** 将配置映射到 Java 对象: ```java @Component @ConfigurationProperties(prefix = "database") public class DatabaseConfig { private String url; private String username; // 省略 getter/setter } ``` 配置文件: ```properties database.url=jdbc:mysql://localhost:3306/test database.username=root ``` --- ### 4. **`@PropertySource` 加载自定义配置文件** 指定非默认配置文件: ```java @Configuration @PropertySource("classpath:custom.properties") public class CustomConfig { @Value("${custom.key}") private String customValue; } ``` --- ### 5. **多环境配置(Profile)** 通过 `application-{profile}.properties` 区分环境: ```properties # application-dev.properties server.port=8080 # application-prod.properties server.port=80 ``` 启动时激活 Profile:`--spring.profiles.active=dev`[^2]。 --- ### 6. **命令行参数** 启动时动态覆盖配置: ```bash java -jar app.jar --server.port=9090 ``` --- ### 7. **环境变量** 通过系统环境变量设置配置: ```bash export SPRING_DATASOURCE_URL=jdbc:mysql://localhost:3306/mydb ``` Spring Boot 会自动将其转换为 `spring.datasource.url`[^3]。 --- ### 8. **YAML 配置文件** 使用 YAML 格式的多层级配置: ```yaml app: name: Demo security: enabled: true ``` 通过 `@Value("${app.security.enabled}")` 注入。 --- ### 9. **`@ImportResource` 导入 XML 配置** 兼容传统 XML 配置: ```java @SpringBootApplication @ImportResource("classpath:legacy-config.xml") public class Application { } ``` --- ### 10. **编程方式读取外部文件** 使用 `ResourceLoader` 加载文件: ```java @Autowired private ResourceLoader resourceLoader; public void readConfig() throws IOException { Resource resource = resourceLoader.getResource("file:/etc/config/app.properties"); Properties props = new Properties(); props.load(resource.getInputStream()); } ``` --- ### 配置加载优先级 Spring Boot 按以下顺序加载配置(高优先级覆盖低优先级): 1. 命令行参数 2. 环境变量 3. `config/` 目录下的配置文件 4. 项目内的配置文件[^3]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值