# 24.外化配置

Spring Boot允许将配置外部化（externalize），这样你就能够在不同的环境下使用相同的代码。你可以使用properties文件，YAML文件，环境变量和命令行参数来外部化配置。使用@Value注解，可以直接将属性值注入到beans中，然后通过Spring的`Environment`抽象或通过`@ConfigurationProperties`[绑定到结构化对象](https://docs.spring.io/spring-boot/docs/2.0.0.RELEASE/reference/htmlsingle/#boot-features-external-config-typesafe-configuration-properties)来访问。

Spring Boot设计了一个非常特别的`PropertySource`顺序，以允许对属性值进行合理的覆盖，属性会以如下的顺序进行设值：

1. home目录下的[devtools全局设置属性](http://docs.spring.io/spring-boot/docs/2.0.0.RELEASE/reference/htmlsingle/#using-boot-devtools-globalsettings)（`~/.spring-boot-devtools.properties`，如果devtools激活）。
2. 测试用例上的[@TestPropertySource](https://docs.spring.io/spring/docs/5.0.4.RELEASE/javadoc-api/org/springframework/test/context/TestPropertySource.html)注解。
3. 测试用例上的[@SpringBootTest#properties](http://docs.spring.io/spring-boot/docs/2.0.0.RELEASE/api/spring-boot-test/src/main/java/org/springframework/boot/test/context/SpringBootTest.html)注解。
4. 命令行参数
5. 来自`SPRING_APPLICATION_JSON`的属性（环境变量或系统属性中内嵌的内联JSON）。
6. `ServletConfig`初始化参数。
7. `ServletContext`初始化参数。
8. 来自于`java:comp/env`的JNDI属性。
9. Java系统属性（System.getProperties()）。
10. 操作系统环境变量。
11. RandomValuePropertySource，只包含`random.*`中的属性。
12. 没有打进jar包的[Profile-specific应用属性](http://docs.spring.io/spring-boot/docs/2.0.0.RELEASE/reference/htmlsingle/#boot-features-external-config-profile-specific-properties)（`application-{profile}.properties`和YAML变量）。
13. 打进jar包中的[Profile-specific应用属性](http://docs.spring.io/spring-boot/docs/2.0.0.RELEASE/reference/htmlsingle/#boot-features-external-config-profile-specific-properties)（`application-{profile}.properties`和YAML变量）。
14. 没有打进jar包的应用配置（`application.properties`和YAML变量）。
15. 打进jar包中的应用配置（`application.properties`和YAML变量）。
16. `@Configuration`类上的[`@PropertySource`注解](https://docs.spring.io/spring/docs/5.0.4.RELEASE/javadoc-api/org/springframework/context/annotation/PropertySource.html)。
17. 默认属性（通过设置`SpringApplication.setDefaultProperties`指定）。

下面是具体的示例，假设你开发一个使用name属性的`@Component`：

```java
import org.springframework.stereotype.*
import org.springframework.beans.factory.annotation.*

@Component
public class MyBean {
    @Value("${name}")
    private String name;
    // ...
}
```

你可以将一个`application.properties`放到应用的classpath下，为`name`提供一个合适的默认属性值。当在新的环境中运行时，可以在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 `Environment`，你可以以`acme.name=test`结尾；如果在一个系统属性中，可以提供作为`spring.application.json`的JSON字符串：

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

或命令行参数：

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

或作为一个JNDI变量`java:comp/env/spring.application.json`。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://jack80342.gitbook.io/spring-boot/iv.-spring-boot-features/24.-externalized-configuration.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
