【更新中】本文大部分内容翻译自官方文档https://docs.spring.io/spring-boot/docs/2.2.5.RELEASE/reference/html/spring-boot-features.html

文章目录

  • 1.Spring应用程序
    • 1.1 启动失败
    • 1.2 延迟初始化
    • 1.3 自定义Banner
    • 1.4 自定义SpringApplication
    • 1.5 构建流式API
    • 1.6 Application事件和监听器
    • 1.7 Web Environment
    • 1.8 访问应用程序参数
    • 1.9 使用ApplicationRunner或CommandLineRunner
    • 1.10 应用程序退出
    • 1.11 管理特性
  • 2. 外部化配置
    • 2.1 配置随机值
    • 2.2 访问命令行属性
    • 2.3 应用程序属性文件
    • 2.4 Profile-specific属性
    • 2.5 占位符属性
    • 2.6 加密属性
    • 2.7 使用YAML代替Properties
      • 2.7.1 加载YAML
      • 2.7.2 将YAML作为Properties公开在Spring环境
      • 2.7.3 Multi-profile YAML文档
      • 2.7.4 YAML的不足
    • 2.8 类型安全的配置属性
      • 2.8.1 JavaBean属性绑定
      • 2.8.2 构造方法绑定
      • 2.8.3 开启```@ConfigurationProperties```注解类型
      • 2.8.4 使用```@ConfigurationProperties```注解类型
      • 2.8.5 第三方配置
      • 2.8.6 宽松的绑定
      • 2.8.7 合并复杂类型
      • 2.8.8 属性转换
        • 转换时间(Converting durations)
        • 转换数据大小(Converting Data Sizes)
      • 2.8.9 @ConfigurationProperties校验
      • 2.8.10 @ConfigurationProperties和@Value
  • 3. 配置文件
    • 3.1 添加活动的配置文件
    • 3.2 以编程方式设置配置文件
    • 3.3 Profile-specific配置文件

1.Spring应用程序

The SpringApplication类提供了一种方便的方法来引导从main()方法启动的Spring应用程序。你可以委托给SpringApplication.run方法,如下所示:

public static void main(String[] args) {SpringApplication.run(Application20200106.class, args);
}

应用程序启动,你应该看到类似以下输出:

  .   ____          _            __ _ _/\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \\\/  ___)| |_)| | | | | || (_| |  ) ) ) )'  |____| .__|_| |_|_| |_\__, | / / / /=========|_|==============|___/=/_/_/_/:: Spring Boot ::   v2.2.2.RELEASE2019-04-31 13:09:54.117  INFO 56603 --- [           main] o.s.b.s.app.SampleApplication            : Starting SampleApplication v0.1.0 on mycomputer with PID 56603 (/apps/myapp.jar started by pwebb)
2019-04-31 13:09:54.166  INFO 56603 --- [           main] ationConfigServletWebServerApplicationContext : Refreshing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@6e5a8246: startup date [Wed Jul 31 00:08:16 PDT 2013]; root of context hierarchy
2019-04-01 13:09:56.912  INFO 41370 --- [           main] .t.TomcatServletWebServerFactory : Server initialized with port: 8080
2019-04-01 13:09:57.501  INFO 41370 --- [           main] o.s.b.s.app.SampleApplication            : Started SampleApplication in 2.992 seconds (JVM running for 3.658)

默认情况下,会显示INFO日志消息,包括一些相关的启动细节,比如启动应用程序的用户。

如果你需要除了INFO级别的日志信息,你可以设置日志级别。

应用程序版本是从主程序类包中的实现版本确定的。

设置spring.main.log-startup-infofalse可以关闭启动日志信息记录。

这还将关闭应用程序活动配置文件的日志记录。

要在启动期间添加额外的日志记录,您可以在SpringApplication的子类中重写logStartupInfo(boolean)

1.1 启动失败

如果您的应用程序启动失败,注册的FailureAnalyzers将有机会提供专用的错误消息和修复问题的具体操作。

例如,如果您在端口8080上启动一个web应用程序,并且该端口已经在使用,您应该看到类似于以下消息:

***************************
APPLICATION FAILED TO START
***************************Description:Embedded servlet container failed to start. Port 8080 was already in use.Action:Identify and stop the process that's listening on port 8080 or configure this application to listen on another port.

Spring Boot提供了很多FailureAnalyzers实现,你也可以创建自定义的故障分析器

如果没有故障分析器能处理异常,你也可以显示完整的条件报告,以便更好地理解出错的原因。您需要为org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener启用debug属性或启用DEBUG日志记录。

例如,如果您使用java -jar运行您的应用程序,您可以启用debug属性,如下所示:

java -jar myproject-0.0.1-SNAPSHOT.jar --debug

1.2 延迟初始化

开启延迟初始化可以减少应用程序所需的世界,在web应用程序中,启用延迟初始化将导致在接收到HTTP请求之前许多与web相关的bean不会被初始化。

延迟初始化的缺点是较晚得发现应用程序中的问题。如果一个错误配置的bean是延迟初始化的,在启动期间不会出现故障,故障会发生bean被初始化的时候。

还必须注意确保JVM有足够的内存来容纳应用程序的所有bean,而不仅仅是只容纳那些在启动期间初始化的bean。

由于这些原因,延迟初始化默认是禁用的,建议在开启延迟初始化之前对JVM的堆大小进行微调(fine-tuning)。

用编程方式开启延迟初始化:

使用SpringApplicationBuilderlazyInitialization方法:

SpringApplicationBuilder springApplicationBuilder = new SpringApplicationBuilder();
springApplicationBuilder.lazyInitialization(true);

使用SpringApplicationsetLazyInitialization方法:

SpringApplication springApplication = new SpringApplication(Application20200106.class);
springApplication.setLazyInitialization(true);

配置文件开启延迟从初始化:

使用spring.main.lazy-initialization属性:

spring.main.lazy-initialization=true

如果你希望一部分bean使用延迟初始化,一部分bean禁用延迟初始化,你可以使用@Lazy(false)注解。

  • lazy = true,表示延迟,默认为true
  • lazy = false,表示不延迟

1.3 自定义Banner

classpath中添加一个banner.txt文件或者设置spring.banner.location属性来改变在启动期间打印的banner。

如果文件编码不是UTF-8,需要设置spring.banner.charset

除了文本文件,还可以在classpath中添加banner.gifbanner.jpgbanner.png图片文件。或者设置spring.banner.image.location属性。

图片被转换成ASCII码打印在任何文本banner上方。

banner.txt文件中,可以使用下列占位符:

表1 Banner变量

变量 说明
${application.version} 应用程序的版本号,和MANIFEST.MF一样的声明。例如,Implementation-Version: 1.0打印成1.0
${application.formatted-version} 应用程序的版本号,和MANIFEST.MF一样,按照格式显示(用圆括号括起来并且加上前缀v)。如(v1.0)
${spring-boot.version} 你在使用的Spring Boot版本,如2.2.2.RELEASE
${spring-boot.formatted-version} 你在使用的Spring Boot版本,按照格式显示(用圆括号括起来并且加上前缀v)。如v2.2.2.RELEASE
${Ansi.NAME} (or ${AnsiColor.NAME}, ${AnsiBackground.NAME}, ${AnsiStyle.NAME}) NAME是ANSI转义码的名称,详情参见AnsiPropertySource
${application.title} 应用程序的Title,和MANIFEST.MF一样。如Implementation-Title: MyApp打印成MyApp

如果你想用编程的方式生成一个banner,可以使用SpringApplication.setBanner(…)

实现org.springframework.boot.Banner接口并重写printBanner()方法。

You can also use the spring.main.banner-mode property to determine if the banner has to be printed on System.out (console), sent to the configured logger (log), or not produced at all (off).

你也可以使用spring.main.banner-mode属性控制banner是否在System.out(console)被打印,或者发送到已配置的日志程序,或者关闭。

打印banner的bean被注册成一个单例bean,名字为:springBootBanner

1.4 自定义SpringApplication

如果默认的SpringApplication不是你的菜,你可以创建一个本地实例并对其设置。例如,关闭banner:

public static void main(String[] args) {SpringApplication springApplication = new SpringApplication(Application20200106.class);springApplication.setBannerMode(Banner.Mode.OFF);springApplication.run(args);
}

传给SpringApplication的构造方法参数是Spring beans的配置源。在大多数情况下,都是引用@Configuration类,但是也可以引用XML配置或引用被扫描的包。

引用XML配置:

ResourceLoader resourceLoader = new ClassPathXmlApplicationContext("config/spring/user/applicationContext-user.xml");
SpringApplication springApplication = new SpringApplication(resourceLoader,Application20200106.class);

引用被扫描的包:

配置类UserConfiguration

package cn.shrmus.springboot.demo20200106.configuration;import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;@ComponentScan("cn.shrmus.springboot.demo20200106.user")
@Configuration
public class UserConfiguration {
}

启动类Application20200106

@Import(value = cn.shrmus.springboot.demo20200106.configuration.UserConfiguration.class)
@SpringBootApplication
public class Application20200106{public static void main(String[] args) {ResourceLoader resourceLoader = new AnnotationConfigApplicationContext("cn.shrmus.springboot.demo20200106.user");
//        ResourceLoader resourceLoader = new AnnotationConfigApplicationContext(cn.shrmus.springboot.demo20200106.configuration.UserConfiguration.class);SpringApplication springApplication = new SpringApplication(resourceLoader,Application20200106.class);ConfigurableApplicationContext configurableApplicationContext = springApplication.run(args);UserController userController = configurableApplicationContext.getBean(UserController.class);System.out.println(userController);SpringApplication.exit(configurableApplicationContext);}

也可以使用application.properties文件配置SpringApplication,详情参考外部化配置。

要查看SpringApplication的完整配置,参考SpringApplicationJavadoc。

1.5 构建流式API

如果需要构建一个ApplicationCOntext层次结构(具有父/子关系的多个上下文),或者你更喜欢使用构建“流式”API,你可以使用SpringApplicationBuilder

The SpringApplicationBuilderlets you chain together multiple method calls and includes parentand childmethods that let you create a hierarchy, as shown in the following example:

使用SpringApplicationBuilder将包含parentchild方法等多个方法的调用都链在一起,以此创建一个层次结构,如下:

new SpringApplicationBuilder().sources(Parent.class).child(Application.class).bannerMode(Banner.Mode.OFF).run(args);

创建ApplicationContext层次结构会有一些限制,Web组件被包含在子上下文中,父上下文和子上下文都使用同一个Environment。阅读SpringApplicationBuilderJavadoc查看详情。

1.6 Application事件和监听器

除了常见的Spring框架事件(如ContextRefreshedEvent)外,SpringApplication还发送一些额外的应用程序事件。

有些事件是在创建ApplicationContext之前触发的,所以不能将监听器注册成@Bean,你可以使用SpringApplication.addListeners(…)方法或SpringApplicationBuilder.listeners(…)方法注册它们。

如果你希望监听器能自动注册,不管应用程序时如何创建的,你可以在META-INF/spring.factories文件中使用org.springframework.context.ApplicationListener添加监听器的引用。如下:

org.springframework.context.ApplicationListener=cn.shrmus.springboot.demo20200106.listener.MyListener

在程序运行时,应用程序事件按一下顺序发送:

  1. ApplicationStartingEvent在运行开始但还没有任何处理之前发送,监听器和初始化的注册除外。
  2. ApplicationEnvironmentPreparedEventEnvironment要在已知的上下文中被使用,但上下文创建之前发送。
  3. ApplicationContextInitializedEventApplicationContext准备好,ApplicationContextInitializers被调用,但还没加载任何bean definitions之前发送。
  4. ApplicationPreparedEvent在bean definitions加载后,启动刷新之前发送。
  5. ApplicationStartedEvent在上下文刷新之后,调用应用程序和命令行运行程序之前发送。
  6. ApplicationReadyEvent在应用程序和命令行运行程序被调用后发送。它表明应用程序已经准备好为请求提供服务。
  7. ApplicationFailedEvent在启动出现异常时发送。

上面的列表只包含绑定到SpringApplication中的SpringApplicationEvent。除此之外,以下事件会在ApplicationPreparedEvnet之后和ApplicationStartedEvent之前发布:

  1. ContextRefreshedEvent在刷新ApplicationContext时发送。

A WebServerInitializedEventis sent after the WebServeris ready. ServletWebServerInitializedEventand ReactiveWebServerInitializedEventare the servlet and reactive variants respectively.

  1. WebServerInitializedEventWebServer准备好之后发送。ServletWebServerInitializedEventReactiveWebServerInitializedEvent分别作用于servlet和reactive。(原文中variants原意是变种)

通常不需要使用应用程序事件,但是知道它们的存在是很方便的。在内部,Spring Boot使用事件处理各种任务。

Application events are sent by using Spring Framework’s event publishing mechanism. Part of this mechanism ensures that an event published to the listeners in a child context is also published to the listeners in any ancestor contexts. As a result of this, if your application uses a hierarchy of SpringApplicationinstances, a listener may receive multiple instances of the same type of application event.

应用程序事件是使用Spring框架的事件发布机制发送的。此机制的一部分确保将事件发布到子上下文中的监听器,也能将事件发布到任何祖先上下文的监听器。因此,如果你的应用程序使用了SpringApplication实例的层次结构,则监听器可能会接收同一类型应用程序事件的多个实例。

To allow your listener to distinguish between an event for its context and an event for a descendant context, it should request that its application context is injected and then compare the injected context with the context of the event. The context can be injected by implementing ApplicationContextAwareor, if the listener is a bean, by using @Autowired.

允许监听器区分它的上下文事件和子上下文的事件,它应该请求注入它的应用程序上下文,然后将注入的上下文与事件的上下文比较。上下文可以通过ApplicationContextAware实现注入,或者,如果监听器是bean,可以通过@Autowired注入。

1.7 Web Environment

一个SpringApplication会替你创建正确类型的ApplicationContext。用于确定WebApplicationType的算法相当简单:

  • 如果存在Spring MVC,使用AnnotationConfigServletWebServerApplicationContext
  • 如果不在存Spring MVC,但是存在Spring WebFlux,使用AnnotationConfigReactiveWebServerApplicationContext
  • 否则,使用AnnotationConfigApplicationContext

这意味着如果你同一个应用程序中使用Spring MVC和来自于Spring WebFlux的WebClinet,那么默认情况下使用Spring MVC。

你也可以通过调用setWebApplicationType(WebApplicationType)来覆盖它。
还可以通过调用setApplicationContextClass(…)完全控制ApplicationContext类型。

在Junit测试中使用ApplicationContext时,通常需要调用setWebApplicationType(WebApplicationType.NONE)

1.8 访问应用程序参数

如果你需要访问传递给SpringApplication.run(…)的应用程序参数,则需要注入org.springframework.boot.ApplicationArguments

The ApplicationArgumentsinterface provides access to both the raw String[]arguments as well as parsed optionand non-optionarguments.

接口ApplicationArguments提供对原始String[]参数和解析过的optionnon-option参数的访问。如下:

import org.springframework.boot.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.stereotype.*;@Component
public class MyBean {@Autowiredpublic MyBean(ApplicationArguments args) {boolean debug = args.containsOption("debug");List<String> files = args.getNonOptionArgs();// if run with "--debug logfile.txt" debug=true, files=["logfile.txt"]}
}

Spring Boot还可以向Spring Environment注册一个CommandLinePropertySource。还可以使用@Value注解注入单个应用程序参数。

1.9 使用ApplicationRunner或CommandLineRunner

如果你需要在SpringApplication启动后运行一些特定的代码,你可以实现ApplicationRunner或者CommandLineRunner接口。

这两个接口以相同的方式工作,并提供一个单一的run方法,这个方法在SpringApplication.run(…)结束之前被调用。

接口CommandLineRunner以简单字符串数组的形式提供对应用程序参数的访问,而ApplicationRunner使用谈论过的ApplicationArguments。下面的例子展示带run方法的CommandLineRunner

import org.springframework.boot.*;
import org.springframework.stereotype.*;@Component
public class MyBean implements CommandLineRunner {public void run(String... args) {// Do something...}
}

如果定义了多个CommandLineRunnerApplicationRunnerbean,必须按特定的顺序调用它们。可以通过实现org.springframework.core.Ordered接口或org.springframework.core.annotation.Order注解控制调用顺序。

1.10 应用程序退出

每个SpringApplication向JVM注册一个shotdown hook确保ApplicationContext在退出时能够优雅地关闭。所有标准的Spring生命周期回调(例如DisposableBean接口或@PreDestroy注解)都会被使用。

另外,如果希望SpringApplication.exit()被调用时返回特殊的退出码,可以实现org.springframework.boot.ExitCodeGenerator接口。这个退出码会被传递给System.exit()作为状态码返回。如下:

@SpringBootApplication
public class ExitCodeApplication {@Beanpublic ExitCodeGenerator exitCodeGenerator() {return () -> 42;}public static void main(String[] args) {System.exit(SpringApplication.exit(SpringApplication.run(ExitCodeApplication.class, args)));}
}

此外,接口ExitCodeGenerator可以由异常实现。当遇到这样的异常,Spring Boot将返回退出码,退出码是实现这个接口时重写getExitCode()方法提供的退出码。

import org.springframework.boot.ExitCodeGenerator;public class CustomizingException extends Exception implements ExitCodeGenerator {@Overridepublic int getExitCode() {return 43;}
}

1.11 管理特性

通过指定spring.application.admin.enabled属性来为应用程序开启管理相关的特性。这将在MBeanServer平台上公开SpringApplicationAdminMXBean。你可以使用这个特性来管理你的Spring Boot远程应用程序。这个特性对于任何服务包装器实现都是有用的。

如果你想知道应用程序在哪个HTTP端口上运行,获取local.server.port属性的值。

2. 外部化配置

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

Spring Boot使用一种非常特殊的PropertySource顺序,其设计目的是允许合理地覆盖值。属性按以下顺序排序:

  1. Devtools全局设置属性在$HOME/.config/spring-boot文件夹中的时候devtools是活动状态。
  2. 在你的测试中使用@TestPropertySource注解。
  3. 在你的测试中使用properties属性。可以在@SpringBootTest和用于在你的应用程序中测试特定部分的测试注解。
  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之外的Profile-specific应用程序属性(application-{profile}.properties和YAML)。
  13. 打包jar之内的Profile-specific应用程序属性(application-{profile}.properties和YAML)。
  14. 打包jar之外的应用程序属性(application.properties和YAML)。
  15. 打包jar之内的应用程序属性(application.properties和YAML)。
  16. @Configuration类上的@PropertySource注解。请注意,在刷新应用程序上下文之前,不会将此类属性源添加到Environment中。在刷新开始之前配置某些属性(例如logging.*spring.main.*)已经太晚了。
  17. 默认属性(通过指定设置SpringApplication.setDefaultProperties)。

举一个具体的例子,假设你开发的一个@Component类使用name属性,如下:

import org.springframework.stereotype.*;
import org.springframework.beans.factory.annotation.*;@Component
public class MyBean {@Value("${name}")private String name;// ...}

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

在带有环境变量的命令行上提供SPRING_APPLICATION_JSON属性,使用下面的UNIX shell:

$ SPRING_APPLICATION_JSON='{"acme":{"name":"test"}}' java -jar myapp.jar

在前面的例子中,在Spring Environmentacme.name=test结束。你还可以在系统属性中用spring.application.json提供JSON。如下:

$ java -Dspring.application.json='{"name":"test"}' -jar myapp.jar

还可以使用命令行参数提供JSON,如下:

$ java -jar myapp.jar --spring.application.json='{"name":"test"}'

还可以使用JNDI变量提供JSON,如下:

java:comp/env/spring.application.json

2.1 配置随机值

用于注入随机值的RandomValuePropertySource是非常有用的(作为秘钥或测试用例)。它可以生成integers,longs,uuids,strings。如下:

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) CLOSE,其中OPEN,CLOSE是任意字符,value,max是整数。如果提供max,则value为最小值,max为最大值(不含)。

2.2 访问命令行属性

默认情况下,SpringApplication将任何命令行选项参数(参数以--开头,如--server.port=9000)转换为property,并将它们添加到Spring Environment中。

As mentioned previously, command line properties always take precedence over other property sources.

就如前面所说,命令行属性始终优先于其它属性源。

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

2.3 应用程序属性文件

加载配置文件:SpringApplication从以下位置的application.properties文件中加载属性并将属性添加到Spring Environment中:

  1. 当前目录的/config子目录
  2. 当前目录
  3. classpath下的/config
  4. classpath的根目录

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

你也可以使用YAML(‘yml’)文件替代’.properties’。

如果不想用application.properties作为配置文件名,你也可以指定spring.config.name环境属性来切换到另一个文件名。还可以使用spring.config.location环境属性来引用一个显示的位置(以逗号分隔的目录位置或文件路径)。

通过spring.config.name指定一个文件名:

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

通过spring.config.location指定文件位置:

$ java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties

spring.config.namespring.config.location很早就用于确定必须加载哪些文件。它们必须定义为环境属性(通常是操作系统环境变量,系统属性,命令行参数)。

如果spring.config.location包含目录(与文件相反),它们应该以/结尾(在运行时,在加载前附加由spring.config.name生成的名称,包含profile-specific文件名)。spring.config.location中指定的文件按原样使用,不支持profile-specific变体,并被任何profile-specific属性覆盖。

配置位置以相反的顺序搜索。默认情况下,配置位置是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:/

This search ordering lets you specify default values in one configuration file and then selectively override those values in another. You can provide default values for your application in application.properties(or whatever other basename you choose with spring.config.name) in one of the default locations. These default values can then be overridden at runtime with a different file located in one of the custom locations.

这种搜索顺序允许您在一个配置文件中指定默认值,然后有选择地在另一个配置文件中覆盖这些值。你可以在一个默认位置的application.properties中为你的应用程序提供默认值(或你选择的任何其他基本的spring.config.name)。在运行时使用位于自定义位置中另一个文件覆盖这些默认值。

如果使用环境变量而不是系统属性,大部分操作系统不允许点分隔(period-separated)的键名,但你可以使用下划线(SPRING_CONFIG_NAME代替spring.config.name)。

如果应用程序在容器中运行,然后可以使用JNDI属性(在java:comp/env中)或servlet上下文初始化参数来代替环境变量或系统属性。

2.4 Profile-specific属性

application.properties文件之外,profile-specific属性也能通过使用application-{profile}.properties命名约定被定义。Environment有一组默认配置文件(默认情况下,[default]),如果没有设置活动配置文件,就使用这些默认配置文件。换句话说,如果没有配置文件被明确激活,那么属性从application-default.properties被加载。

Profile-specific属性从与标准application.properties相同的位置加载,使用profile-specific文件总是覆盖non-specific文件,不管profile-specific文件位于打包的jar的内部或外部。

If several profiles are specified, a last-wins strategy applies. For example, profiles specified by the spring.profiles.activeproperty are added after those configured through the SpringApplicationAPI and therefore take precedence.

如果多个配置文件被指定,则应用最后配置的策略。例如,spring.profiles.active属性指定的配置文件添加在通过SpringApplicationAPI配置之后,因此优先。

假设application.properties中有如下配置:

spring.profiles.active=pro,dev

最终生效的是application-dev.properties文件。

如果你在spring.config.location指定了一些文件,profile-specific的变体不被考虑。如果你想使用profile-specific属性,在spring.config.location中使用目录。

2.5 占位符属性

文件application.properties中的值在使用时通过现有的Environment过滤,所以你可以返回到以前定义的值(例如,系统属性中定义的值)。

app.name=MyApp
app.description=${app.name} is a Spring Boot application

您还可以使用此技术创建现有Spring Boot属性的“短”变体。点击howto.html查看详情。

2.6 加密属性

Spring Boot不提供任何对属性值加密的支持,然而,它提供了修改Spring Environment中包含的值所必须的hook点。EnvironmentPostProcessor接口允许你在应用启动之前操作(manipulate)Environment。点击howto.html查看详情。

如果您正在寻找一种安全的方式来存储凭证和密码,Spring Cloud Vault项目提供了在HashiCorp Vault中存储外部化配置的支持。

2.7 使用YAML代替Properties

YAML是JSON的超集,因此是指定分层配置数据的一种方便的格式。当你的classpath中有SnakeYAML库时,SpringApplication类自动支持YAML作为properties的另一种选择。

SnakeYAML是由spring-boot-starter自动提供的。

2.7.1 加载YAML

Spring框架提供了两个方便的类用于加载YAML文档。YamlPropertiesFactoryBean将YAML加载为PropertiesYamlMapFactoryBean将YAML加载为Map

例如:参考以下YAML文档:

environments:dev:url: https://dev.example.comname: Developer Setupprod:url: https://another.example.comname: My Cool App

将上述YAML文档转换为下列properties:

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

YAML列表用[index]作为引用,代表属性键。如下:

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

将上述YAML文档转换为下列properties:

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;}
}

2.7.2 将YAML作为Properties公开在Spring环境

YamlPropertySourceLoader可将YAML作为PropertySource公开在Spring环境中。这样就可以使用带有占位符语法的@Value注解来访问YAML属性。

2.7.3 Multi-profile YAML文档

通过使用spring.profiles键,你可以在一个文件中指定多个profile-specific YAML文档,指定文档何时应用,如下:

server:address: 192.168.1.100
---
spring:profiles: development
server:address: 127.0.0.1
---
spring:profiles: production & eu-central
server:address: 192.168.1.120

如果development配置文件是激活的,那么server.address的属性值为127.0.0.1

同理,如果productioneu-central配置文件是激活的,server.address的属性值为192.168.1.120

如果developmentproductioneu-central配置文件都没有启用,那么server.address的属性值为192.168.1.100

spring.profiles可以包含简单的配置文件名(如production)或配置文件表达式。配置文件表达式允许表达更复杂的配置文件逻辑,如production & (eu-central | eu-west)。查看参考指南了解更多详情。

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

server:port: 8000
---
spring:profiles: defaultsecurity:user:password: weak

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

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

Spring profiles designated by using the spring.profileselement may optionally be negated by using the !character. If both negated and non-negated profiles are specified for a single document, at least one non-negated profile must match, and no negated profiles may match.

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

2.7.4 YAML的不足

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

在profile-specific YAML文件中使用multi YAML文档语法可能导致意外发生。如下:

application-dev.yml

server:port: 8000
---
spring:profiles: "!test"security:user:password: "secret"

如果使用参数--spring.profiles.active=dev运行应用程序,你可能希望security.user.password设置为secret,但是并不会。

嵌套的文档将被过滤,因为主文件名为application-dev.yml。它已经被认为是profile-specific,嵌套文档将被忽略。

建议不要将profile-specific YAML文件和多个YAML文档混合使用。只使用其中一个。

2.8 类型安全的配置属性

使用@Value("${property}")注解注入配置属性有时会很麻烦(cumbersome),特别(especially)是在处理多个属性或数据本质上是分层的情况下。Spring Boot提供了另一种处理属性的方法,允许强类型bean控制和验证应用程序的配置。

请参见@Value类型安全的配置属性之间的区别。

2.8.1 JavaBean属性绑定

可以绑定一个声明标准JavaBean属性的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"对象,其名称由属性的名称决定。特别是(In particular),返回类型没有被使用,可能是SecurityProperties
  • acme.security.password
  • acme.security.roles,默认是USERString集合。

Spring Boot自动配置大量使用@ConfigurationProperties来轻松配置自动配置的bean。

类似于自动配置类,在Spring Boot中可用的@ConfigurationProperties类仅供内部使用。

The properties that map to the class, which are configured via properties files, YAML files, environment variables etc., are public API but the content of the class itself is not meant to be used directly.

映射到类的属性(通过属性文件、YAML文件、环境变量等配置)是公共API,但是类本身的内容并不意味着可以直接(directly)使用。

这种安排依赖于(relies on)默认的空构造函数,getter和setter通常是强制性的(mandatory),因为绑定是通过标准的Java bean属性描述符进行的,就像在Spring MVC中一样。在下列情况下可省略setter:

  • 只要映射被初始化,就需要一个getter,但不一定是setter,因为绑定器可以对它们进行修改。
  • 可以通过索引(通常使用YAML)或使用单个逗号分隔(comma-separated)的值(属性)访问集合和数组。在后一个情况下,setter是必需的。我们建议始终为此类型添加setter。如果你初始化一个集合,请确保它是可变的(not immutable)(如前面的实例所示)。
  • 如果初始化了嵌套的POJO属性(如前面示例中的Security字段),则不需要setter。如果你想用绑定器使用其默认构造方法动态(on the fly)创建一个实例,则需要setter。

有些人使用Lombok自动添加getter和setter。请确保Lombok不会为这样的类型生成任何特定的(particular)构造方法,因为容器会自动使用它来实例化对象。

最后,只有标准Java Bean属性被支持,不支持绑定静态属性。

2.8.2 构造方法绑定

上一节的示例可以在不变的情况下(in an immutable fashion)重写,如下所示:

package com.example;import java.net.InetAddress;
import java.util.List;import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.ConstructorBinding;
import org.springframework.boot.context.properties.DefaultValue;@ConstructorBinding
@ConfigurationProperties("acme")
public class AcmeProperties {private final boolean enabled;private final InetAddress remoteAddress;private final Security security;public AcmeProperties(boolean enabled, InetAddress remoteAddress, Security security) {this.enabled = enabled;this.remoteAddress = remoteAddress;this.security = security;}public boolean isEnabled() { ... }public InetAddress getRemoteAddress() { ... }public Security getSecurity() { ... }public static class Security {private final String username;private final String password;private final List<String> roles;public Security(String username, String password,@DefaultValue("USER") List<String> roles) {this.username = username;this.password = password;this.roles = roles;}public String getUsername() { ... }public String getPassword() { ... }public List<String> getRoles() { ... }}}

在这个设置中,@ConstructorBinding注解用于指示(indicate)应该使用构造函数绑定。

This means that the binder will expect to find a constructor with the parameters that you wish to have bound.

这意味着绑定器将期望找到带参数的构造方法,而这些参数是已绑定的。

具有@ConstructorBinding类的内部类(如上面示例中的Security)也将通过其构造函数绑定。

可以使用@DefaultValue指定默认值,并用相同的转换服务将String值强制(coerce)转换为缺失属性的目标类型。

要使用构造函数绑定,必须使用启动@EnableConfigurationProperties或配置属性扫描。由常规Spring机制创建的bean(如@Componentbean,通过(via)@Bean方法创建的bean,或者通过@Import加载的bean)不能使用构造函数绑定。

如果您的类有多个构造方法,您还可以直接在需要绑定的构造方法上使用@ConstructorBinding

2.8.3 开启@ConfigurationProperties注解类型

Spring Boot提供了绑定@ConfigurationProperties类型并将它们注册为bean的基础设施(infrastructure)。你可以逐个类地启用配置属性,或启用与组件扫描工作方式类似的配置属性扫描。

有时候,用@ConfigurationProperties注解的类不适合扫描,例如,如果您正在开发自己的自动配置,或者希望有条件地启用它们。在这些情况下,使用@EnableConfigurationProperties注解指定要处理的类型列表。这个注解可以用在任何@Configuration类上,如下:

@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(AcmeProperties.class)
public class MyConfiguration {
}

要想使用配置属性扫描,要将@ConfigurationPropertiesScan注解添加到你的应用程序中。通常(typically),它被添加到使用@SpringBootApplication注解的主应用程序类中,但@ConfigurationPropertiesScan注解也可以被添加到任何@Configuration类中。默认情况下,将对声明注解的类的包进行扫描。如果你想扫描特定的包,你可以按下面的例子来做:

@SpringBootApplication
@ConfigurationPropertiesScan({ "com.example.app", "org.acme.another" })
public class MyApplication {
}

@ConfigurationPropertiesbean使用配置属性扫描或通过@EnableConfigurationProperties注册时,这个bean户有一个按照惯例的(conventional)名称:<prefix>-<fqn>,其中<prefix>是在@ConfigurationProperties注解中指定的环境键前缀,<fqn>是bean的全限定名(the fully qualified name of the bean)。如果注解不提供任何前缀,则只使用bean的全限定名。

上述2.8.2的例子中的bean名是acme-com.example..AcmeProperties

建议@ConfigurationProperties只处理(deal with)环境,特别(in particular)是不从上下文注入其他bean。对于极端(corner)情况,可以使用setter注入或框架提供的任何*Aware接口(例如你要访问Environment可以使用EnvironmentAware)。如果你仍然要使用构造方法注入其他bean,则必须使用@Component注解配置属性bean,并使用JavaBean属性绑定。

2.8.4 使用@ConfigurationProperties注解类型

这种配置方式在SpringApplication外部的YAML配置中特别好用,如下面的例子所示:

# application.ymlacme:remote-address: 192.168.1.1security:username: adminroles:- USER- ADMIN# additional configuration as required

要使用@ConfigurationPropertiesbean,你可以与任何其他bean相同的方式注入它们,如下所示:

@Service
public class MyService {private final AcmeProperties properties;@Autowiredpublic MyService(AcmeProperties properties) {this.properties = properties;}//...@PostConstructpublic void openConnection() {Server server = new Server(this.properties.getRemoteAddress());// ...}}

Using @ConfigurationProperties also lets you generate metadata files that can be used by IDEs to offer auto-completion for your own keys.

使用@ConfigurationProperties还可以生成元数据文件,IDE可以使用这些元数据文件为你的键提供自动完成功能。详见appendix。

2.8.5 第三方配置

除了(as well as)使用@ConfigurationProperties注解类外,您还可以在公共@Bean方法上使用它。当你想将属性绑定到超出你控制范围外的第三方组件时,这样做特别有用。

Environment属性配置bean,将@ConfigurationProperties添加到它的bean registration中,如下所示:

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

Any JavaBean property defined with the anotherprefix is mapped onto that AnotherComponentbean in manner similar to the preceding AcmePropertiesexample.

使用another前缀定义的任何JavaBean属性都将以类似前面的(preceding)AcmeProperties示例的方式映射到AnotherComponentbean。

2.8.6 宽松的绑定

Spring Boot使用一些宽松的(relaxed)规则将Environment属性绑定到@ConfigurationPropertiesbeans中,因此,Environment属性名和bean属性名不需要完全匹配(exact match)。有用的常见示例包括短横线分隔的(dash-speparated)环境属性(如context-path绑定到contextPath),以及大写的(capitalized)环境属性(如PORT绑定到port)。如下所示:

@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;}}

使用上述代码,可以使用以下属性名:

表2 宽松的绑定

属性 描述
acme.my-project.person.first-name 短横线分隔的(kebab case)命名方式,建议在.properties.yml文件中使用。
acme.myProject.person.firstName 标准驼峰命名法(Standard camel case syntax)。
acme.my_project.person.first_name 下划线命名法(Underscore notation),它是.properties.yml文件中使用的另一种格式(alternative format)。
ACME_MYPROJECT_PERSON_FIRSTNAME 大写命名法(upper case format),建议用于系统环境变量。

注解的prefix值必须是短横线分隔的命名方式(小写用-分隔,如acme.my-project..person)。

表3 每个属性源的宽松的绑定规则

属性源 简单的 列表
Properties文件 驼峰命名法,短横线分隔命名法,或下划线命名法 使用[]的标准列表语法(syntax)或逗号分隔的值(comma-separated)
YAML文件 驼峰命名法,短横线分隔命名法,或下划线命名法 标准的YAML列表语法或逗号分隔的值
环境变量 用下划线作为分隔符的大写命名法。_不应在属性名中使用 被下划线环绕(surrounded)的数值(numeric values)。例如MY_ACME_1_OTHER = my.acme[1].other
系统变量 驼峰命名法,短横线分隔命名法,或下划线命名法 使用[]的标准列表语法(syntax)或逗号分隔的值(comma-separated)

建议属性存储为小写的短横线分隔的命名方法,如my.property-name=acme

绑定到Map属性时,如果key包含除了(other than)小写字母,数字字符(alpha-numeric characters),或-之外的任何内容,你需要使用括号符号(bracket notation),以便原来的(original)值被保存(is preserved)。如果key没有被[]环绕(is not surrounded),任何不是字母数字或-的字符都被删除。例如,以下属性绑定到Map

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

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

For YAML files, the brackets need to be surrounded by quotes for the keys to be parsed properly.

YAML文件,要正确解析键,方括号(brackets)需要用引号(quotes)包围。

2.8.7 合并复杂类型

当有多个列表配置在多个地方,通过覆盖来替换整个列表。

例如,假设MyPojo对象的namedescription属性默认为null。下面展示一个AcmeProperties类中包含MyPojo列表:

@ConfigurationProperties("acme")
public class AcmeProperties {private final List<MyPojo> list = new ArrayList<>();public List<MyPojo> getList() {return this.list;}
}

使用下面的配置:

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

如果dev配置文件不是活动的,AcmeProperties.list包含了一个MyPojo,如前面定义的那样。如果dev配置文件被启用,list仍然只包含一个元素(name值为my another name并且description值为null),该配置不会向list中添加第二个MyPojo实例,并且不会合并项(items)。

List被指定在多个配置文件中时,具有最高优先级的那个(并且只使用那个)被使用。如下所示:

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

在前面的例子中,如果dev配置文件是活动的,AcmeProperties.list包含了一个MyPojoname值为my another name并且description值为null)。对于YAML,可以使用逗号分隔的列表和YAML列表来完全覆盖list的内容。

对于Map属性,你可以绑定来自多个源的属性值。但是,对于多个源中的相同属性,将使用具有最高优先级的属性。下面展示一个AcmeProperties类中包含Map<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 1description: my description 1
---
spring:profiles: dev
acme:map:key1:name: dev name 1key2:name: dev name 2description: dev description 2

如果dev配置文件不是活动的,AcmeProperties.map包含一个key1name值为my name 1并且description值为my description 1)。如果dev文件被启用,map包含两个元素key1name值为dev name 1并且description值为my description 1)和key2name值为dev name 2并且description值为dev description 2

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

2.8.8 属性转换

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

因为这个bean是在应用程序生命周期的早期请求的,因此确保限制ConversionService使用的依赖项。通常,任何你需要的依赖项可能在创建时没有完全初始化。你可能希望重命名自定义ConversionService,如果不需要配置keys则强制执行,并且只依赖于使用@ConfigurationPropertiesBinding的自定义转换器。

转换时间(Converting durations)

Spring Boot提供专门的工具来表达时间。如果你公开一个java.time.Duration属性,在应用程序属性中可使用以下格式:

  • 常规long表达(使用毫秒(milliseconds)作为默认单元,除非已指定@DurationUnit
  • java.time.Duration使用的标准ISO-8601格式
  • 一种更具可读性的格式,值和单位是耦合(coupled)的(例如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表示纳秒(nanosecond)
  • us表示微秒(microsecond)
  • ms表示毫秒(millisecond)
  • s表示秒(second)
  • m表示分(minute)
  • h表示时(hour)
  • d表示天(day)

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

如果你从以前的版本升级到使用Long来表示时间,如果切换到Duration的单位不是毫秒,请确保使用@DurationUnit定义这个单位。这样做提供了一个透明的升级路径,同时提供更丰富的格式。

转换数据大小(Converting Data Sizes)

Spring框架有一个以字节表示大小的DataSize值类型。如果你公开一个DataSize属性,在应用程序属性中可使用以下格式:

  • 常规long表达(使用字节作为默认单元,除非已指定@DataSizeUnit
  • java.time.Duration使用的标准ISO-8601格式
  • 一种更具可读性的格式,值和单位是耦合(coupled)的(例如10MB表示10兆)

如下所示:

@ConfigurationProperties("app.io")
public class AppIoProperties {@DataSizeUnit(DataUnit.MEGABYTES)private DataSize bufferSize = DataSize.ofMegabytes(2);private DataSize sizeThreshold = DataSize.ofBytes(512);public DataSize getBufferSize() {return this.bufferSize;}public void setBufferSize(DataSize bufferSize) {this.bufferSize = bufferSize;}public DataSize getSizeThreshold() {return this.sizeThreshold;}public void setSizeThreshold(DataSize sizeThreshold) {this.sizeThreshold = sizeThreshold;}
}

指定10兆字节的缓冲区大小,1010MB都可以。256字节的大小阈值可以指定为256256B

还可以使用任何支持的单位,如:

  • B表示字节(byte)
  • KB表示千字节(kilobyte)
  • MB表示兆字节(megabyte)
  • GB表示千兆字节,吉字节(gigabyte)
  • TB表示兆兆字节,太字节(terabyte)

默认单位是字节,可以使用@DataSizeUnit覆盖,如上面的例子所示。

如果你从以前的版本升级到使用Long来表示字节,如果切换到DataSize的单位不是字节,请确保使用@DataSizeUnit定义这个单位。这样做提供了一个透明的升级路径,同时提供更丰富的格式。

2.8.9 @ConfigurationProperties校验

当用Spring的@Validated注解类时,Spring引导尝试验证ConfigurationProperties类。你可以直接在配置类上使用JSR-303 javax.validation约束注解。要做到这一点,请确保兼容的JSR-303实现在classpath上,然后向字段中添加约束注解,如下所示:

@ConfigurationProperties(prefix="acme")
@Validated
public class AcmeProperties {@NotNullprivate InetAddress remoteAddress;// ... getters and setters}

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

确保始终对嵌套(nested)属性触发验证,即使没有找到属性,也必须使用@Valid注解关联的(associated)字段。下面的例子建立在前面的AcmeProperties例子上:

@ConfigurationProperties(prefix="acme")
@Validated
public class AcmeProperties {@NotNullprivate InetAddress remoteAddress;@Validprivate final Security security = new Security();// ... getters and setterspublic static class Security {@NotEmptypublic String username;// ... getters and setters}
}

你还可以通过创建一个名为configurationPropertiesValidator的bean definition来添加自定义Spring Validator@Bean方法应该声明为静态的。配置属性验证器(validator)是在应用程序生命周期的早期创建的,将@Bean方法声明为静态方法可以在创建bean的时候不用实例化(instantiate)@Configuration类。这样做可以避免任何可能由早期实例化引起的问题。

模块spring-boot-actuator包含一个公开所有@ConfigurationPropertiesbean的终端。将web浏览器指向/actuator/configprops或使用等效的JMX终端。点击生产预备特性查看详情。

2.8.10 @ConfigurationProperties和@Value

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

特性 @Configuration @Value
宽松的绑定(Relaxed binding) Yes No
元数据支持(Meta-data support) Yes No
SpEL表达式 No Yes

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

最后,虽然您可以在@Value中编写SpEL表达式,但是这样的表达式不会从应用程序属性文件中处理。

3. 配置文件

Spring配置文件提供了一种方法来隔离(segregate)应用程序配置的各个部分,并使其仅在某些环境中可用。任何@Component@Configuration@ConfigurationProperties都可以标记为@Profile来限制它的加载时间,如下所示:

@Configuration(proxyBeanMethods = false)
@Profile("production")
public class ProductionConfiguration {// ...}

如果ConfigurationProperties类是通过EnableConfigurationProperties注册的而不是通过自动扫描注册的,@Profile注解需要在具有@EnableConfigurationProperties注解的@Configuration类上指定。在扫描@ConfigurationProperties的情况下,可以在@ConfigurationProperties类本身上指定@Profile

你可以使用spring.profiles.active``````Environment属性指定哪些配置文件是活动的。你可以使用前面描述的任何方式指定属性。例如,你可以在application.properties中包含它,如下所示:

spring.profiles.active=dev,hsqldb

你还可以在命令行使用参数:--spring.profiles.active=dev,hsqldb

3.1 添加活动的配置文件

属性spring.profiles.active遵循与其他属性相同的顺序规则:优先使用优先级最高的PropertySource。这意味着你可以在application.properties中指定活动配置文件,然后使用命令行开关替换它们。

有时,将profil-specific文件的属性添加到active profiles比替换更有用。spring.profiles.include属性可用于无条件地添加active profiles。SpringApplication入口点还有一个用于设置其他配置文件的Java API(也就是说,在spring.profiles.active属性激活的对象之上)。参见SpringApplication中的setAdditionalProfiles()方法。

例如,当使用开关运行具有以下属性的应用程序时,--spring.profiles.active=prodproddbprodmq配置文件也被激活:

---
my.property: fromyamlfile
---
spring.profiles: prod
spring.profiles.include:- proddb- prodmq

请记住,可以在YAML文档中定义spring.profiles属性,以确定配置中何时包含此特定文档。有关详细信息,请阅读howto.html。

3.2 以编程方式设置配置文件

在应用程序运行之前,可以通过调用SpringApplication.setAdditionalProfiles(…)以编程方式设置active profiles。也可以通过使用Spring的ConfigurableEnvironment接口来激活配置文件。

3.3 Profile-specific配置文件

Profile-specific的两个不同的设置,application.properties(或application.yml)和通过@ConfigurationProperties引用的文件都被视为文件并加载。有关详细信息,请阅读Profile-specific属性。

【译】Spring Boot Features相关推荐

  1. 关于Spring Boot你不得不知道的事

    1 Spring Boot官网[2.1.5 CURRENT GA] 1.1 Pivotal Wiki Pivotal Software, Inc. is a software and services ...

  2. spring boot 2.5.5 reference chapter 5 生词

    5 Upgrading Spring Boot check the "migration guide" on the project wiki that provides deta ...

  3. Spring Boot 2.0.0参考手册_中英文对照_Part I

    文章作者:Tyan 博客:noahsnail.com Part I. Spring Boot Documentation This section provides a brief overview ...

  4. 使用Spring Boot指南(零)

    如果您是从Spring Boot或" Spring"开始的,请先阅读本节.它回答了基本的"什么?","如何?"和"为什么?&quo ...

  5. Spring Boot 官方文档中文版

    目前为最新版 2.5.5. 其他spring文档不断更新中 目前为最新版 2.5.5. 其他spring文档不断更新中 总目录 Spring Boot Reference Documentation ...

  6. 【Spring Boot】Spring Boot Logging 示例 | 日志记录

    文章目录 logging.level | 设置日志级别 logging.file | 指定输出日志文件的路径和名称 logging.path | 指定输出日志文件的路径 logging.pattern ...

  7. spring boot 中 log4j2 日志无法加载(Feature 'http://apache.org/xml/features/xinclude' is not recognized.)

    Spring boot 1.5.14 版本中使用 log4j2 日志,在 eclipse 中可以打印日志,但是打包成 war 后,直接运行无法将日志输出到日志文件,配置的 log4j2-spring. ...

  8. 【译】Spring Boot 2.0 官方迁移指南

    前提 希望本文档将帮助您把应用程序迁移到 Spring Boot 2.0. 在你开始之前 首先,Spring Boot 2.0 需要 Java 8 或更高版本.不再支持 Java 6 和 7 了. 在 ...

  9. 译:Spring Boot 自动伸缩

    原文链接:https://dzone.com/articles/spring-boot-autoscaler 作者:Piotr Mińkowski 译者:helloworldtang 自动伸缩是每个人 ...

最新文章

  1. AtCoder AGC030C Coloring Torus (构造)
  2. java学习笔记2022.1.12
  3. Linux sse 地址对齐指令,SSE指令:哪些CPU可以执行原子16B内存操作?
  4. 有了二叉查找树、平衡树为啥还需要红黑树?
  5. 外卖匹配系统_歧视外卖员的北京SKP是个什么东西?
  6. 安居客检测到网页抓取_python3爬虫实战-安居客写字楼信息,学会月入上万理所当然...
  7. Windows IP测试小脚本
  8. a*算法的时间复杂度_算法的时间复杂度:大O表示法
  9. Nokia 920板砖自救(理论上通用,升级Win10成板砖也可以用这个恢复)
  10. win10 64位下Oracle10g安装
  11. 如何拥有类似 hi@hahah.fun 的个人专属域名的邮箱
  12. stata进行无交互效应模型选择—混合模型,个体效应固定,时间效应固定,双向固定和随机效应
  13. Oracle 18c新特性一览
  14. 痞子衡嵌入式:语音处理工具Jays-PySPEECH诞生记(5)- 语音识别实现(SpeechRecognition, PocketSphinx0.1.15)
  15. 如何排查计算机联网故障,电脑莫名连不上网?佰佰教你如何排除网络连接故障!...
  16. python音频转数组_python音频处理的示例详解
  17. Ajax 前后端数据交互
  18. Windows应用、注册表
  19. 管理者必须具备的四大能力
  20. html中bak是什么文件怎么打开,bak文件怎么打开

热门文章

  1. HDLBits学习记录
  2. 04FPGA组合逻辑—多路选择器(二选一)
  3. 秋雨绸缪---又是一年入秋时
  4. Java策略模式(Strategy)
  5. 【Web前端第二阶段--Bootstrap】Day05
  6. 基于SQLite开发的Android记账APP
  7. Minecraft 1.12.2 Java Edition 打开前没有shaderpacks文件夹,如何加光影?
  8. Speedoffice(word)如何文字居中对齐
  9. 6个压箱底的资源网站,质量高还免费,大厂都在用
  10. PySpark简介、搭建以及使用