第 3 章:符合十二要素程序风格的配置
本章系统梳理了如何实现十二要素应用的外部化配置,涵盖 Spring 配置机制、Profile 管理、Spring Boot 配置加载顺序、类型安全配置、以及 Spring Cloud Config 的集中式配置与动态刷新能力。
配置的基本概念与挑战
在 Spring 体系中,“配置”既包括 bean 装配的元数据,也包括运行环境下会变化的参数(如密码、端口、主机名等)。十二要素应用强调将环境相关的配置外部化,避免敏感信息硬编码,提升安全性与可移植性。
Spring 框架对配置的支持
Spring 早期通过 PropertyPlaceholderConfigurer
支持外部属性文件,将 XML 配置中的占位符替换为外部值。如下所示:
<context:property-placeholder location="classpath:some.properties"/>
<bean class="classic.Application">
<property name="configurationProjectName" value="${configuration.projectName}" />
</bean>
这种方式支持将敏感或环境相关配置从代码中剥离,便于在不同环境下灵活切换。
Environment 接口与 @Value 注解
Spring 3.x 引入了 Environment
接口和 @Value
注解,进一步简化了配置注入。你可以通过 @PropertySource
注解加载外部属性文件,通过 @Value
注解将配置注入到字段、构造器或方法参数中。例如:
@Configuration
@PropertySource("some.properties")
public class Application {
@Value("${configuration.projectName}")
private String projectName;
@Autowired
public Application(@Value("${configuration.projectName}") String pn) { ... }
@Autowired
void setEnvironment(Environment env) {
// 通过 env.getProperty("configuration.projectName") 获取配置
}
}
这种机制支持多种注入方式,灵活适配不同场景。
Profile 机制与多环境配置
Spring 的 Profile 机制允许根据不同环境激活不同的 bean 定义。你可以通过 @Profile
注解或配置文件激活不同 profile,实现开发、测试、生产等多环境的灵活切换。例如:
@Configuration
@Profile("prod")
@PropertySource("some-prod.properties")
public class ProdConfiguration { ... }
@Configuration
@Profile({"default", "dev"})
@PropertySource("some.properties")
public class DefaultConfiguration { ... }
通过 spring.profiles.active
配置项、环境变量、JVM 参数或编程方式激活 profile。
Spring Boot 的配置加载顺序与 YAML 支持
Spring Boot 进一步简化了配置加载流程,支持多种配置来源,优先级如下:
- 命令行参数
- JNDI 属性
- JVM 系统属性
- 操作系统环境变量
- 外部配置文件(config/application.yml/properties)
- 内部配置文件(classpath 下的 application.yml/properties)
- @PropertySource 注解
- 默认属性
支持 profile 的配置文件命名规则,如 application-dev.yml
。YAML 格式天然支持层级结构,适合复杂配置场景。例如:
configuration:
projectName: Spring Boot
management:
security:
enabled: false
类型安全的配置绑定
Spring Boot 支持通过 @ConfigurationProperties
注解将配置自动绑定到 POJO,实现类型安全。例如:
@Component
@ConfigurationProperties("configuration")
public class ConfigurationProjectProperties {
private String projectName;
// getter/setter
}
在主类加 @EnableConfigurationProperties
,即可自动注入配置对象。
配置中心与 Spring Cloud Config
对于分布式系统,集中式配置管理尤为重要。Spring Cloud Config Server 提供 REST API,将配置集中存储于 Git/SVN 等仓库,支持版本控制和审计。典型服务端配置如下:
@SpringBootApplication
@EnableConfigServer
public class Application { ... }
application.yml
配置示例:
server:
port: 8888
spring:
cloud:
config:
server:
git:
uri: https://github.com/cloud-native-java/config-server-configuration-repository
客户端通过 spring.application.name
与配置仓库文件名匹配,优先加载 bootstrap.yml
配置:
spring:
application:
name: configuration-client
cloud:
config:
uri: http://localhost:8888
安全与动态刷新
Spring Cloud Config 支持对配置仓库和服务端的安全认证。客户端可通过 URI 携带用户名密码,服务端可通过 Spring Security 保护。
动态刷新方面,@RefreshScope
注解可使 bean 支持配置热更新。通过调用 /refresh
或 /bus/refresh
Actuator 端点,可实现单实例或集群级别的配置刷新。例如:
@RestController
@RefreshScope
class ProjectNameRestController {
@Value("${configuration.projectName}")
private String projectName;
// ...
}
结合 Spring Cloud Bus,可通过消息中间件(如 RabbitMQ、Kafka)实现多实例配置同步刷新。
总结
本章系统梳理了 Spring 及 Spring Boot 的外部化配置机制、Profile 管理、类型安全配置绑定,以及 Spring Cloud Config 的集中式配置与动态刷新能力。通过这些机制,云原生应用能够实现环境无关、配置灵活、运维高效的目标,为后续微服务与自动化运维打下坚实基础。