12

24. 外部化配置

Spring Boot允许你外部化你的配置,这样你就可以在不同的环境中使用相同的应用程序代码,你可以使用properties文件、YAML文件、环境变量和命令行参数来外部化配置,属性值可以通过使用@Value注解直接注入到你的bean中,通过Spring的Environment抽象访问,或者通过@ConfigurationProperties绑定到结构化对象。

Spring Boot使用一种非常特殊的PropertySource命令,该命令旨在允许对值进行合理的覆盖,属性按以下顺序考虑:

  1. Devtools全局设置属性在你的主目录(~/.spring-boot-devtools.properties当devtools处于激活状态时。
  2. 测试中的@TestPropertySource注解
  3. 测试中的@SpringBootTest#properties注解属性
  4. 命令行参数
  5. 来自SPRING_APPLICATION_JSON(嵌入在环境变量或系统属性中的内联JSON)的属性
  6. ServletConfig初始化参数
  7. ServletContext初始化参数
  8. java:comp/env中的JNDI属性
  9. Java系统属性(System.getProperties()
  10. 操作系统环境变量
  11. 一个只有random.*属性的RandomValuePropertySource
  12. 在你的jar包之外的特殊配置文件的应用程序属性application-{profile}.propertiesYAML 变体)
  13. 在jar中打包的特殊配置文件的应用程序属性application-{profile}.propertiesYAML 变体)
  14. 在你的jar包之外的应用程序属性(application.propertiesYAML 变体)
  15. 打包在jar中的应用程序属性(application.propertiesYAML 变体)
  16. @PropertySource注解在你的@Configuration类上
  17. 默认属性(通过设置SpringApplication.setDefaultProperties指定)

为了提供一个具体的示例,假设你开发了一个使用name属性的@Component,如下例所示:

import org.springframework.stereotype.*;
import org.springframework.beans.factory.annotation.*;

@Component
public class MyBean { 

   @Value("${name}")
   private String name;

   // ...
}

在你的应用程序类路径(例如,在jar包中)你可以有一个application.properties文件为name提供一个合理的默认属性值。在新环境中运行时,可以在你的jar包之外提供一个application.properties以覆盖name。对于一次性测试,你可以使用特定的命令行开关启动(例如,java -jar app.jar --name=“Spring”)。

SPRING_APPLICATION_JSON属性可以在带有环境变量的命令行上提供,例如,你可以在UN*X shell中使用以下一行:
$ SPRING_APPLICATION_JSON='{"acme":{"name":"test"}}' java -jar myapp.jar
在前面的示例中,在Spring Environment中你最终得到了acme.name=test,你也可以提供JSON作为spring.applicatio.json在系统属性中,如下例所示:
$ java -Dspring.application.json='{"name":"test"}' -jar myapp.jar
你还可以使用命令行参数来提供JSON,如下面的示例所示:
$ java -jar myapp.jar --spring.application.json='{"name":"test"}'
你还可以将JSON作为JNDI变量提供,如下所示:java:comp/env/spring.application.json

24.1 配置随机值

RandomValuePropertySource用于注入随机值(例如,在secrets或测试用例中),它可以生成integerlonguuidstring,如下面的示例所示:

my.secret=${random.value} 
my.number=${random.int} 
my.bignumber=${random.long} 
my.uuid=${random.uuid} 
my.number.less.than.ten=${random.int(10)} 
my.number.in.range=${random.int[1024,65536]}

random.int*语法是OPEN value (,max) CLOSEOPEN,CLOSE中是任何字符并且value,max是整数。如果提供了max,那么value就是最小值,max是最大值(唯一的)。

24.2 访问命令行属性

在默认情况下,SpringApplication会转换任何命令行选项参数(也就是说,参数从--开始,像--server.port=9000)到一个property,并将它们添加到Spring Environment中,如前所述,命令行属性总是优先于其他属性源。

如果不希望将命令行属性添加到Environment中,你可以使用SpringApplication.setAddCommandLineProperties(false)禁用它们。

24.3 应用程序属性文件

SpringApplication在以下位置从application.properties文件加载属性并将它们添加到Spring Environment:

  1. 当前目录子目录的/config
  2. 当前目录
  3. 类路径下/config
  4. 类路径的根目录

列表按优先顺序排序(在列表中较高的位置定义的属性覆盖在较低位置定义的属性)。

你还可以使用YAML ('.yml')文件作为'.properties'的替代。

如果你不喜欢application.properties作为配置文件名,可以通过指定spring.config.name环境属性切换到另一个文件名,你还可以使用spring.config.location环境属性来引用一个显式的位置(它是一个逗号分隔的目录位置或文件路径列表),下面的示例演示如何指定不同的文件名:

$ java -jar myproject.jar --spring.config.name=myproject

下面的示例演示如何指定两个位置:

$ java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/
override.properties
spring.config.namespring.config.location很早就被用于确定哪些文件必须被加载,因此它们必须被定义为环境属性(通常是一个OS环境变量、一个系统属性或一个命令行参数)。

如果spring.config.location包含目录(相对于文件),它们应该以/结束(并且在运行时,附加的名字来自spring.config.name之前被加载,包括特殊配置文件的文件名)。spring.config.location中指定的文件是按原样使用的,不支持特殊配置文件的变体,并且被任何特殊配置文件的属性覆盖。

配置位置按相反顺序搜索,默认情况下,配置的位置是classpath:/classpath:/config/file:./file:./config/。由此产生的搜索顺序如下:

  1. file:./config/
  2. file:./
  3. classpath:/config/
  4. classpath:/

当自定义配置位置使用spring.config.location配置时,它们替换默认的位置。例如,如果spring.config.location配置值为classpath:/custom-config/file:./custom-config/,搜索顺序如下:

  1. file:./custom-config/
  2. classpath:custom-config/

或者,当自定义配置位置使用spring.config.additional-location配置时,除了默认位置外,还使用它们,在默认位置之前搜索额外的位置。例如,如果额外位置classpath:/custom-config/file:./custom-config/被配置,搜索顺序如下:

  1. file:./custom-config/
  2. classpath:custom-config/
  3. file:./config/
  4. file:./
  5. classpath:/config/
  6. classpath:/

这个搜索排序允许你在一个配置文件中指定默认值,然后在另一个配置文件中选择性地覆盖这些值。你可以在application.properties为你的应用程序提供默认值(或你在spring.config.name中选择的其他basename)位于默认位置之一。这些默认值可以在运行时被重写,并在一个定制的位置中放置一个不同的文件。

如果你使用环境变量而不是系统属性,大多数操作系统都不允许使用周期分隔的键名,但是你可以使用下划线(例如,SPRING_CONFIG_NAME而不是spring.config.name)。
如果应用程序在容器中运行,那么可以使用JNDI属性(在java:comp/env)或servlet上下文初始化参数,而不是环境变量或系统属性。

24.4 特殊配置文件的属性

除了application.properties文件,特殊配置文件的属性也可以通过以下命名约定来定义:application-{profile}.propertiesEnvironment有一组默认配置文件(默认情况下是[default]),如果没有设置活动配置文件,则使用默认配置文件。换句话说,如果没有显式激活配置文件,则加载application-default.properties中的属性。

特殊配置文件的属性从与标准application.properties相同的位置加载,特殊配置文件的文件总是覆盖非特定的文件,无论特殊配置文件的文件是在打包的jar内部还是外部。

如果多个特殊配置文件,则使用应用最后一个的策略,例如,由spring.profiles.active属性添加的特殊配置文件在通过SpringApplication API配置的配置文件之后添加,因此优先级更高。

如果在spring.config.locaction中指定了任何文件,不考虑这些文件的特定配置文件的变体。如果你还想同时使用特殊配置文件,在spring.config.location中使用目录

24.5 属性中的占位符

application.properties中的值在使用时通过现有Environment进行过滤,因此你可以返回到以前定义的值(例如,来自系统属性)。

app.name=MyApp
app.description=${app.name} is a Spring Boot application
你还可以使用此技术来创建现有Spring boot属性的“Short”变体,详细信息请参阅第74.4节“使用‘Short’命令行参数”。

24.6 使用YAML代替属性

YAMLJSON的超集,因此是指定分层配置数据的一种方便的格式,只要类路径上有SnakeYAML库,SpringApplication类就会自动支持YAML作为属性的替代。

如果你使用“Starters”,SnakeYAML将由spring-boot-starter自动提供。

24.6.1 加载YAML

Spring框架提供了两个方便的类,可以用来加载YAML文档。YamlPropertiesFactoryBean以属性装载YAML,而YamlMapFactoryBeanMap的形式装载YAML。

例如,参考以下YAML文档:

environments: 
  dev:
    url: http://dev.example.com
    name: Developer Setup 
  prod:
    url: http://another.example.com 
    name: My Cool App

前面的示例将转换为以下属性:

environments.dev.url=http://dev.example.com 
environments.dev.name=Developer Setup 
environments.prod.url=http://another.example.com 
environments.prod.name=My Cool App

YAML列表表示为[index]解释器的属性键,例如,参考以下YAML:

my: 
  servers:
    - dev.example.com
    - another.example.com

前面的例子将被转换为这些属性:

my.servers[0]=dev.example.com 
my.servers[1]=another.example.com

通过使用Spring Boot的Binder工具(这是@ConfigurationProperties所做的)来绑定到类似的属性,你需要在目标bean中有一个java.util.List(或Set)属性并且还需要提供一个setter或使用变量初始化它。例如,下面的示例绑定到前面显示的属性:

@ConfigurationProperties(prefix="my")
public class Config {

  private List<String> servers = new ArrayList<String>();

  public List<String> getServers() { 
    return this.servers;
  } 
}

24.6.2 将YAML公开为Spring环境中的属性

YamlPropertySourceLoader类可用于在Spring Environment中将YAML公开为PropertySource,这样做可以使用带有占位符语法的@Value注解来访问YAML属性。

24.6.3 多个YAML配置文件

你可以使用spring.profiles键在单个文件中指定多个特殊配置YAML文档来指示你文档何时应用,如下所示:

server:
  address: 192.168.1.100
---
spring:
  profiles: development
server:
  address: 127.0.0.1
---
spring:
  profiles: production
server:
  address: 192.168.1.120

在前面的例子中,如果development配置文件是激活的,server.address属性是127.0.0.1。类似地,如果production配置文件是激活的,server.address属性是192.168.1.120。如果不启用developmentproduction配置文件,则属性的值为192.168.1.100

如果在应用程序上下文启动时没有显式激活,默认配置文件被激活。因此,在接下来的YAML中,我们为仅在“默认”配置文件中可用的spring.security.user.password设置了一个值:

server: 
  port: 8000
---
spring:
  profiles: default 
  security:
    user:
    password: weak

然而,在下面的示例中,密码总是被设置,因为它没有附加到任何配置文件中,而且将在所有其他配置文件中显式地设置被重置:

server: 
  port: 8000
spring: 
  security:
    user:
    password: weak

使用spring.profiles元素指定的Spring配置文件可以选择性的使用字符否定。如果为单个文档指定了否定的和非否定的配置文件,则至少必须匹配一个非否定的配置文件,并且不能匹配任何否定的配置文件。

24.6.4 YAML的缺点

YAML文件不能被@PropertySource注解加载,因此,在需要以这种方式加载值的情况下,需要使用属性文件。

24.7 类型安全的配置属性文件

使用@Value(“${property}”)注解注入配置属性有时会很麻烦,尤其是当你处理多个属性或你的数据本质上是层次化的时候,Spring Boot提供了另一种处理属性的方法,该方法允许强类型bean管理和验证应用程序的配置。

package com.example;

import java.net.InetAddress; 
import java.util.ArrayList; 
import java.util.Collections; 

import java.util.List;
import org.springframework.boot.context.properties.ConfigurationProperties; 

@ConfigurationProperties("acme")
public class AcmeProperties {
    
    private boolean enabled;
    private InetAddress remoteAddress;
    
    private final Security security = new Security();

    public boolean isEnabled() { ... }
    
    public void setEnabled(boolean enabled) { ... }

    public InetAddress getRemoteAddress() { ... }

    public void setRemoteAddress(InetAddress remoteAddress) { ... } 

    public Security getSecurity() { ... }

    public static class Security {

        private String username;
        private String password;

        private List<String> roles = new ArrayList<>(Collections.singleton("USER")); 

        public String getUsername() { ... }
        
        public void setUsername(String username) { ... }
        
        public String getPassword() { ... }
        
        public void setPassword(String password) { ... }
        
        public List<String> getRoles() { ... }
        
        public void setRoles(List<String> roles) { ... }
    } 
}

前一个POJO定义了以下属性:

  • acme.enabled,默认值为false
  • acme.remote-address,可以从String强转的类型
  • acme.security.username,使用嵌套的“ security”对象,该对象的名称由属性的名称决定,特别是,返回类型根本不使用,并且可能是SecurityProperties
  • acme.security.password
  • acme.security.roles,使用一个String集合

getter和setter通常是强制性的,因为绑定是通过标准的Java bean属性描述符,就像在Spring MVC中一样,在以下情况下可以省略setter:

  • Map,只要初始化了它们,就需要一个getter,但不一定需要setter,因为绑定器可以对它们进行转变。
  • 可以通过索引(通常是YAML)或使用单个逗号分隔值(属性)来访问集合和数组,在后一种情况下,setter是必需的。我们建议始终为此类类型添加一个setter,如果初始化一个集合,请确保它不是不可变的(如前面的示例所示)。
  • 如果初始化嵌套POJO属性(如前面示例中的Security字段),则不需要setter,如果你希望绑定器使用它的默认构造函数来动态创建实例,那么你需要一个setter。

有些人使用Lombok项目自动添加getter和setter,确保Lombok没有为此类类型生成任何特定的构造函数,因为容器会自动使用它来实例化对象。

最后,只考虑标准的Java Bean属性,不支持对静态属性的绑定。


还可以查看@Value@ConfigurationProperties之间的差异。

你还需要列出要在@EnableConfigurationProperties注解中注册的属性类,如下例所示:

@Configuration 
@EnableConfigurationProperties(AcmeProperties.class) 
public class MyConfiguration {
}
当以@ConfigurationProperties这种方式注册bean时,bean有一个常规名称:<prefix>-<fqn>,其中<prefix>是在@ConfigurationProperties注解中指定的环境key前缀,<fqn>是bean的完全限定名,如果注解不提供任何前缀,则只使用bean的完全限定名。

上面示例中的bean名称是acme-com.example.AcmeProperties

即使前面的配置为AcmeProperties创建了一个常规bean,我们建议@ConfigurationProperties只处理环境,特别是从上下文中不注入其他bean。话虽如此,@EnableConfigurationProperties注解也自动应用于你的项目,使任何已添加@ConfigurationProperties注解的bean都可以从Environment中配置。你可以通过确保AcmeProperties已经是一个bean来简化MyConfiguration,如下面的示例所示:

@Component 
@ConfigurationProperties(prefix="acme") 
public class AcmeProperties {
 // ... see the preceding example
}

这种配置风格与SpringApplication外部YAML配置配合得特别好,如下例所示:

# application.yml

acme:
  remote-address: 192.168.1.1
  security: 
    username: admin 
    roles:
      - USER 
      - ADMIN
# additional configuration as required

要使用@ConfigurationProperties bean,可以像其他bean一样对它们进行注入,如下例所示:

@Service
public class MyService {

  private final AcmeProperties properties;

  @Autowired
  public MyService(AcmeProperties properties) { 
    this.properties = properties;
  }

  //...
 
  @PostConstruct
  public void openConnection() {
    Server server = new Server(this.properties.getRemoteAddress()); 
    // ...
  } 
}
使用@ConfigurationProperties还可以生成可以被IDE使用的元数据文件,为你自己的键提供自动完成。详细信息请参阅附录B,配置元数据附录

24.7.1 第三方配置

除了使用@ConfigurationProperties来注解类之外,还可以在公开的@Bean方法中使用它,当你希望将属性绑定到控件之外的第三方组件时,这样做特别有用。

要从Environment属性配置bean,请向其bean注册中添加@ConfigurationProperties,如下例所示:

@ConfigurationProperties(prefix = "another") 
@Bean
public AnotherComponent anotherComponent() {
  ... 
}

another前缀定义的任何属性都被映射到与前面的AcmeProperties示例类似的另一个组件bean。

24.7.2 宽松绑定

Spring Boot使用一些宽松的规则将Environment属性绑定到@ConfigurationProperties bean,因此不需要在Environment属性名和bean属性名之间进行精确匹配,这很有用的常见示例包括:分体环境属性(例如,context-path绑定到contextPath)和大写的环境属性(例如,PORT绑定到port)。

例如,参考下面的@ConfigurationProperties类:

@ConfigurationProperties(prefix="acme.my-project.person")
public class OwnerProperties {

  private String firstName;

  public String getFirstName() { 
    return this.firstName;
  }

  public void setFirstName(String firstName) { 
    this.firstName = firstName;
  }  
}

在前面的示例中,可以使用以下属性名称:

属性 提示
acme.my-project.person.first-name 连接符形式,建议在.properties.yml文件中使用
acme.myProject.person.firstName 标准的驼峰式大小写语法
acme.my_project.person.first_name 下划线表示法,这是在.properties.yml文件中使用的另一种格式
ACME_MYPROJECT_PERSON_FIRSTNAME 在使用系统环境变量时推荐使用大写格式
注解的prefix值必须使用连接符形式(小写并且使用-分隔,如acme.my-project.person)。

表24.2,放宽了每个属性源的绑定规则

属性源 样例 列表
属性文件 驼峰式大小写,连接符大小写,或下划线符号 使用[]或逗号分隔值的标准列表语法
YAML文件 驼峰式大小写,连接符大小写,或下划线符号 标准的YAML列表语法或逗号分隔的值
环境变量 以下划线作为分隔符的大写格式,不应该在属性名中使用_ 由下划线包围的数值,例如MY_ACME_1_OTHER = my.acme[1].other
系统属性 驼峰式大小写,连接符大小写,或下划线符号 使用[]或逗号分隔值的标准列表语法
我们建议,在可能的情况下,属性以小写的连接符格式存储,例如my.property-name=acme

在绑定到Map属性时,如果key不包含小写字母数字字符或-,则需要使用括号符号,以便保留原始值。如果键没有被[]包围,任何非字母数字或-的字符都会被删除,例如,考虑将以下属性绑定到Map

acme:
  map:
    "[/key1]": value1
    "[/key2]": value2
    /key3: value3

上面的属性将绑定到以/key1/key2key3作为Map中的键的Map

24.7.3 合并复杂类型

当在多个地方配置列表时,通过替换整个列表来重写。

例如,假设一个MyPojo对象的namedescription属性默认为null,下面的示例公开了来自AcmePropertiesMyPojo对象列表:

@ConfigurationProperties("acme")
public class AcmeProperties {

    private final List<MyPojo> list = new ArrayList<>();

    public List<MyPojo> getList() {
        return this.list;
    }

}

参考如下配置:

acme:
  list:
    - name: my name
      description: my description
---
spring:
  profiles: dev
acme:
  list:
    - name: my another name

如果dev配置文件不是激活的,AcmeProperties.list包含一个MyPojo条目,正如前面定义的。如果启用了dev配置文件,然而,该列表仍然只包含一个条目,(以my another name的名称和null的描述),此配置不向列表添加第二个MyPojo实例,也不合并条目。

当一个List在多个配置文件中指定时,使用具有最高优先级的(且仅使用该优先级),参考下面的例子:

acme:
  list:
    - name: my name
      description: my description
    - name: another name
      description: another description
---
spring:
  profiles: dev
acme:
  list:
    - name: my another name

在前面的例子,如果dev配置文件是激活的,AcmeProperties.list包含一个MyPojo条目(以my another name作为name和null的description),对于YAML,可以使用逗号分隔的列表和YAML列表完全覆盖列表的内容。

对于Map属性,你可以使用来自多个源的属性值进行绑定,但是,对于多个源中的相同属性,使用优先级最高的属性。下面的示例公开了AcmePropertiesMap<String, MyPojo>:

@ConfigurationProperties("acme")
public class AcmeProperties {

    private final Map<String, MyPojo> map = new HashMap<>();

    public Map<String, MyPojo> getMap() {
        return this.map;
    }

}

参考如下配置:

acme:
  map:
    key1:
      name: my name 1
      description: my description 1
---
spring:
  profiles: dev
acme:
  map:
    key1:
      name: dev name 1
    key2:
      name: dev name 2
      description: dev description 2

如果dev配置文件不是激活的,AcmeProperties.map包含一个键key1的条目(一个my name 1的name和一个my description 1的description)。如果启用了dev配置文件,然而,map包含键key1(name为dev name 1,description为my description 1)和key2(name为dev name 2,description为dev description 2)的两个条目。

前面的合并规则适用于来自所有属性源的属性,而不仅仅是YAML文件。

24.7.4 属性转换

Spring Boot试图在绑定到@ConfigurationProperties bean时将外部应用程序属性强制转换到正确的类型,如果需要自定义类型转换,你可以提供一个ConversionService bean(一个名为ConversionService的bean)或自定义属性编辑器(通过一个CustomEditorConfigurer bean)或自定义Converters(使用@ConfigurationPropertiesBinding注解定义的bean)。

因为这个bean在应用程序生命周期的早期就被请求,确保限制你的ConversionService正在使用的依赖项。
通常,你需要的任何依赖项在创建时可能不会被完全初始化,如果配置键强制转换不需要自定义ConversionService,并且只依赖于使用@ConfigurationPropertiesBinding限定的自定义转换器,那么你可能希望重命名自定义转换服务。
转换持续时间

Spring Boot支持表示持续时间,如果你公开一个java.time.Duration属性,在应用程序属性中有以下格式:

  • 一个常规的long表示(使用毫秒作为默认单位,除非指定了@DurationUnit
  • 使用java.util.Duration的标准的ISO-8601格式
  • 一个更可读的格式,其中的值和单位是耦合的(例如,10s意味着10秒)

参考下面的例子:

@ConfigurationProperties("app.system")
public class AppSystemProperties {

    @DurationUnit(ChronoUnit.SECONDS)
    private Duration sessionTimeout = Duration.ofSeconds(30);

    private Duration readTimeout = Duration.ofMillis(1000);

    public Duration getSessionTimeout() {
        return this.sessionTimeout;
    }

    public void setSessionTimeout(Duration sessionTimeout) {
        this.sessionTimeout = sessionTimeout;
    }

    public Duration getReadTimeout() {
        return this.readTimeout;
    }

    public void setReadTimeout(Duration readTimeout) {
        this.readTimeout = readTimeout;
    }

}

指定30秒的会话超时,30PT30S30s都是等价的,可以在以下任何形式中指定500ms的读超时:500PT0.5S500ms

你还可以使用任何受支持的单元,这些都是:

  • 纳秒使用ns
  • 毫秒使用ms
  • 秒使用s
  • 分钟使用m
  • 小时使用h
  • 天使用d

默认的单位是毫秒,可以使用@DurationUnit覆盖,如上面的示例所示。

如果你正在升级以前的版本,只是使用Long来表示持续时间,如果不是在切换到Duration时的毫秒数,确保定义单元(使用@DurationUnit)。这样做可以提供透明的升级路径,同时支持更丰富的格式。

24.7.5 @ConfigurationProperties Validation

每当使用Spring的@validate注解@ConfigurationProperties类时,Spring Boot都会尝试验证这些类。你可以直接在配置类上使用JSR-303 javax.validation约束注解。为此,请确保在你的类路径上有一个兼容的JSR-303实现,然后向你的字段添加约束注解,如下面的示例所示:

@ConfigurationProperties(prefix="acme")
@Validated
public class AcmeProperties {

    @NotNull
    private InetAddress remoteAddress;

    // ... getters and setters

}
你还可以通过注解@Bean方法来触发验证,该方法使用@Validated创建配置属性。

尽管嵌套属性在绑定时也会被验证,将相关字段注解为@Valid是很好的实践,这确保即使没有找到嵌套属性,也会触发验证。以下示例基于前面的AcmeProperties示例:

@ConfigurationProperties(prefix="acme")
@Validated
public class AcmeProperties {

    @NotNull
    private InetAddress remoteAddress;

    @Valid
    private final Security security = new Security();

    // ... getters and setters

    public static class Security {

        @NotEmpty
        public String username;

        // ... getters and setters

    }

}

你还可以通过创建一个名为configurationPropertiesValidator的bean定义来添加一个定制的Spring Validator@Bean方法应该声明为static,配置属性验证器是在应用程序生命周期的早期创建的,并且将@Bean方法声明为静态,这样就可以创建bean,而不必实例化@Configuration类。这样做可以避免早期实例化可能导致的任何问题。这里有一个属性验证示例,展示了如何设置。

spring-boot-actuator模块包含公开所有@ConfigurationProperties bean的端点,将web浏览器指向/actuator/configprops或使用等效的JMX端点。有关详细信息,请参阅“生产就绪特性”一节。

24.7.6 @ConfigurationProperties和@Value

@Value注解是一个核心容器特性,它不提供与类型安全配置属性相同的特性,下表总结了@ConfigurationProperties@Value支持的特性:

特性 @ConfigurationProperties @Value
宽松绑定 YES NO
元数据支持 YES NO
SpEL评估 NO YES

如果你为自己的组件定义了一组配置键,我们建议你将它们分组到带有@ConfigurationProperties注解的POJO中。你还应该注意,由于@Value不支持宽松绑定,因此如果你需要通过使用环境变量来提供值,那么它不是一个很好的选择。

最后,当你可以在@Value中编写SpEL表达式,这些表达式不会从应用程序属性文件中处理。


上一篇:SpringApplication
下一篇:配置文件

博弈
2.5k 声望1.5k 粉丝

态度决定一切