Spring Boot 配置源詳解(完整版)
一、配置源加載順序與優先級
配置源類型 | 優先級順序(從高到低) | 對應配置類/接口 | 是否可覆蓋 | 典型文件/來源 |
---|---|---|---|---|
命令行參數(--key=value ) | 1(最高) | SimpleCommandLinePropertySource (org.springframework.core.env ) | 是 | 啟動參數(如 java -jar app.jar --server.port=9090 ) |
SPRING_APPLICATION_JSON | 2 | MapPropertySource (org.springframework.core.env ) | 是 | 環境變量或系統屬性(如 -Dspring.application.json={...} ) |
系統環境變量 | 3 | SystemEnvironmentPropertySource (org.springframework.core.env ) | 是 | 操作系統環境變量(如 export APP_NAME=myapp ) |
@PropertySource 注解 | 4 | PropertySourcesPropertyResolver (org.springframework.core.env ) | 是 | 代碼中指定的資源路徑(如 classpath:custom.properties ) |
ServletConfig 初始化參數 | 5 | ServletConfigPropertySource (org.springframework.boot.env ) | 是 | Web 容器配置(如 Tomcat 的 context-param ) |
ServletContext 初始化參數 | 6 | ServletContextPropertySource (org.springframework.boot.env ) | 是 | Web 容器配置(如 Tomcat 的 init-param ) |
JNDI 環境變量 | 7 | JndiPropertySource (org.springframework.core.env ) | 是 | JNDI 服務器配置(如 java:comp/env ) |
隨機屬性(random.* ) | 8 | RandomValuePropertySource (org.springframework.boot.env ) | 否 | 自動生成隨機值(如 random.number=12345 ) |
類路徑 application.properties /.yml | 9 | YamlPropertySourceLoader , PropertiesPropertySourceLoader (org.springframework.boot.env ) | 否 | src/main/resources/application.properties |
資源目錄 application.properties | 10 | ResourcePropertySource (org.springframework.core.env ) | 是 | 外部目錄(如 /config/application.properties ) |
Profile 特定配置(如 application-dev.properties ) | 11 | ProfileSpecificPropertySource (org.springframework.boot.env ) | 是 | src/main/resources/application-{profile}.properties |
外置配置文件(如 external-config/application.properties ) | 12 | ExternalConfigPropertySource (org.springframework.boot.env ) | 是 | 外置路徑(如 /opt/config/application.properties ) |
二、配置源加載流程詳解
-
初始化 Environment:
- Spring Boot 啟動時,通過
SpringApplication
創建Environment
對象(類型StandardEnvironment
)。 Environment
管理所有配置源的集合PropertySources
。
- Spring Boot 啟動時,通過
-
加載引導配置:
- 通過
PropertySourceBootstrapConfiguration
加載bootstrap.yml/properties
(用于配置加密、外部配置文件路徑等)。
- 通過
-
逐層加載配置源:
- 使用
PropertySourceLoader
加載不同格式的配置文件(如 YAML、Properties):// 例如加載 YAML 文件 YamlPropertySourceLoader loader = new YamlPropertySourceLoader(); Resource resource = new ClassPathResource("application.yml"); PropertySource<?> yamlSource = loader.load("application", resource, 0); environment.getPropertySources().addLast(yamlSource);
- 使用
-
合并配置源:
- 按優先級順序合并所有
PropertySource
,高優先級覆蓋低優先級的同名屬性。
- 按優先級順序合并所有
三、配置轉換過程
-
屬性解析:
- 通過
ConfigurationPropertySources
將所有PropertySource
轉換為ConfigurationPropertySource
:// 示例:解析屬性路徑 ConfigurationPropertyName name = ConfigurationPropertyName.of("server.port");
- 通過
-
綁定到 Bean:
- 使用
Binder
將屬性值綁定到@ConfigurationProperties
注解的 Bean:@ConfigurationProperties(prefix = "app") public class AppProperties {private String name;private int timeout;// getters/setters }@SpringBootApplication @EnableConfigurationProperties(AppProperties.class) // 必須啟用 public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);} }
- 使用
-
類型轉換:
- 通過
ConversionService
處理類型轉換(如String
轉Integer
):@Bean public ConversionService conversionService() {GenericConversionService service = new GenericConversionService();service.addConverter(String.class, Integer.class, s -> Integer.parseInt(s));return service; }
- 通過
四、嵌套與替換規則
-
變量替換:
- 支持
${key}
語法引用其他屬性:# application.properties base.url=http://example.com api.url=${base.url}/api
- 支持
-
優先級覆蓋:
- 高優先級配置源的值覆蓋低優先級的同名屬性:
# application.properties: server.port=8080 # 命令行參數:--server.port=9090 → 最終值為 9090
- 高優先級配置源的值覆蓋低優先級的同名屬性:
-
多文檔合并:
- 同名屬性按加載順序依次覆蓋,最終保留最高優先級的值。
五、配置源對比表
配置源類型 | 位置/來源 | 是否可覆蓋 | 典型使用場景 | 代碼示例 |
---|---|---|---|---|
命令行參數 | 啟動參數 | 是 | 運行時動態配置 | java -jar app.jar --server.port=9090 |
SPRING_APPLICATION_JSON | 環境變量或系統屬性 | 是 | 簡單 JSON 配置 | -Dspring.application.json='{ "server": { "port": 9090 } }' |
系統環境變量 | 操作系統環境變量 | 是 | 生產環境全局配置 | export SPRING_DATASOURCE_URL=jdbc:mysql://localhost:3306/db |
@PropertySource 注解 | 代碼指定的資源路徑 | 是 | 內嵌特定配置文件 | ```java |
\n@Configuration\n@PropertySource(“classpath:custom.properties”)\n``` | ||||
外置配置文件 | 文件系統(如 /config ) | 是 | 生產環境外部配置 | /config/application.properties |
Profile 特定配置 | 類路徑或外置路徑 | 是 | 不同環境差異化配置 | application-dev.properties |
六、代碼示例
1. 系統環境變量覆蓋
# 操作系統環境變量設置:
export APP_NAME="ProductionApp"
// 使用 @Value 注入
@Value("${APP_NAME}")
private String appName;
2. 隨機屬性使用
# application.properties
random.seed=12345
@Value("${random.number}")
private int randomNum; // 自動生成隨機數
3. JNDI 配置示例
// JNDI 配置(需容器支持)
@Resource(name = "java:comp/env/jdbc/datasource")
private DataSource dataSource;
4. 外置配置文件激活
# 啟動命令指定配置路徑:
java -jar app.jar --spring.config.location=file:/opt/config/application.properties
5. Profile 特定配置
# application-dev.properties
spring.datasource.url=jdbc:mysql://localhost:3306/dev
// 啟動時指定 Profile:
java -jar app.jar --spring.profiles.active=dev
七、總結表格
配置源類型 | 優先級 | 對應類/接口 | 是否可覆蓋 | 典型文件/來源 | 示例 |
---|---|---|---|---|---|
命令行參數 | 高 | SimpleCommandLinePropertySource | 是 | 啟動參數 | --server.port=9090 |
系統環境變量 | 中 | SystemEnvironmentPropertySource | 是 | 操作系統環境變量 | export SPRING_DATASOURCE_URL=jdbc:mysql://localhost:3306/db |
類路徑 application.properties | 低 | PropertiesPropertySourceLoader | 否 | 內置資源路徑 | src/main/resources/application.properties |
外置配置文件 | 中低 | ExternalConfigPropertySource | 是 | 外部文件路徑 | /config/application.properties |
關鍵代碼類參考
- 加載器:
YamlPropertySourceLoader
,PropertiesPropertySourceLoader
(org.springframework.boot.env
) - 環境管理:
StandardEnvironment
,ConfigurableEnvironment
(org.springframework.core.env
) - 綁定機制:
Binder
,ConfigurationPropertyBindingPostProcessor
(org.springframework.boot.context.properties
)
通過上述流程,Spring Boot 實現了靈活且可擴展的配置管理能力,開發者可根據需求選擇合適的配置源并控制優先級。