maf*_*aff 5 java backwards-compatibility spring-boot spring-boot-configuration
是否有推荐的方法将重组/重命名引入外部化配置,同时为仍然依赖旧配置结构的消费者保持向后兼容性?
例如,给定一个库使用@ConfigurationProperties过去定义的以下配置结构:
old-properties:
an:
old-property: true
another:
custom-property: 1234
Run Code Online (Sandbox Code Playgroud)
该库的新版本将配置重新定义为如下所示:
my-library:
a-property: true
another-property: 1234
Run Code Online (Sandbox Code Playgroud)
有没有一种好方法可以弃用旧的结构,同时在一段时间内保持对现有消费者的兼容性?使用新版本库的消费者应该仍然能够使用old-properties.an.old-property并自动映射到my-library.a-property.
我知道使用附加配置元数据将属性标记为已弃用的功能,但我正在明确寻找一种支持两个版本以简化迁移的方法。
Spring Boot 配置处理器@DeprecatedConfigurationProperty为此目的提供了一个注释。生成的元数据文件将包含任何原因/替换注释,如果使用带注释的属性,这会导致记录适当的弃用警告。
请参阅此处的基本示例。CassandraProperties.java中的以下代码片段显示了一个实际用例,其中spring.data.cassandra.cluster-name已弃用,取而代之的是spring.data.cassandra.session-name. 通过简单地调用已弃用属性的 getter/setter 中替换属性的 getter/setter 来处理向后兼容性:
public String getSessionName() {
return this.sessionName;
}
public void setSessionName(String sessionName) {
this.sessionName = sessionName;
}
@Deprecated
@DeprecatedConfigurationProperty(replacement = "spring.data.cassandra.session-name")
public String getClusterName() {
return getSessionName();
}
@Deprecated
public void setClusterName(String clusterName) {
setSessionName(clusterName);
}
Run Code Online (Sandbox Code Playgroud)
要为未映射到@ConfigurationPropertiesbean 的属性实现相同的行为,您可以在 中手动指定它们META-INF/additional-spring-configuration-metadata.json并添加运行时依赖项org.springframework.boot:spring-boot-properties-migrator。请参阅Spring Boot 文档以供参考。
spring-boot-autoconfigure中的以下片段显示了一个实际用例,其中server.servlet.path已被弃用,取而代之的是spring.mvc.servlet.path. 向后兼容性由PropertiesMigrationListener处理,它“自动重命名具有匹配替换的键,并记录所发现内容的报告”。:
{
"name": "server.servlet.path",
"type": "java.lang.String",
"description": "Path of the main dispatcher servlet.",
"defaultValue": "/",
"deprecation": {
"replacement": "spring.mvc.servlet.path",
"level": "error"
}
},
Run Code Online (Sandbox Code Playgroud)
如果您设置了 deprecated 属性server.servlet.path=/foo,则替换属性@Value("${spring.mvc.servlet.path}")将计算为/foo,并且将在启动时记录弃用通知。
我研究了 Spring Boot 如何处理(已被替换)的弃用阶段logging.filelogging.file.name,并且当他们直接在代码中实现回退时,我决定尝试类似的方法,@ConfigurationProperties在一个@Bean方法中创建新的,该方法处理从旧属性名称设置值(如果可用) 。
鉴于新的配置结构如下所示(为简洁起见,使用 Lombok):
import lombok.Data;
@Data
public class MyLibraryConfigurationProperties {
private String aProperty;
private String anotherProperty;
}
Run Code Online (Sandbox Code Playgroud)
该@Bean方法现在负责读取旧值并将其应用于属性:
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
@Configuration
public class MyLibraryConfiguration {
@Bean
@ConfigurationProperties(prefix = "my-library")
public MyLibraryConfigurationProperties myLibraryConfigurationProperties(Environment environment) {
MyLibraryConfigurationProperties config = new MyLibraryConfigurationProperties();
// fallback to old property if available
if (environment.containsProperty("old-properties.an.old-property")) {
// here we could also log warnings regarding the deprecation
config.setAProperty(environment.getProperty("old-properties.an.old-property"));
}
return config;
}
}
Run Code Online (Sandbox Code Playgroud)
如果新值也通过配置设置,它将覆盖旧属性设置的值。
| 归档时间: |
|
| 查看次数: |
1681 次 |
| 最近记录: |