第 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 的集中式配置与动态刷新能力。通过这些机制,云原生应用能够实现环境无关、配置灵活、运维高效的目标,为后续微服务与自动化运维打下坚实基础。

文章导航

独立页面

这是书籍中的独立页面。

书籍首页

评论区