在Spring Boot项目中,YML文件中的配置可以自动转换为@ConfigurationProperties
注释bean,我从官方文档和源代码中发现ApplicationConversionService#addApplicationConverters()
方法中添加了一个默认的LenientStringToEnumConverterFactory
来处理所有字符串转换为Enum,它通过Enum.valueOf()
实现,但我想使用其他规则将字符串转换为Enum的示例,就像下面的fromAlias()
方法一样,
@ConfigurationProperties(prefix = "head")
@Component
@Data
public class HeadProperties {
private PayType payType;
private Integer cast;
@Getter
@RequiredArgsConstructor
enum PayType {
GOLD("GOLD", "金币"), DIAMOND("DIAMOND", "钻石"), VIP_FREE("VIP_FREE", "会员免费");
private final String val;
private final String alias;
static PayType fromAlias(String alias) {
return Arrays.stream(values())
.filter(type -> alias.equals(type.getAlias()))
.findAny()
.orElse(null);
}
}
}
以下是YML文件配置
head:
payType: "金币"
cast: 10
我不知道条目在哪里,所以程序一运行我就得到一个错误代码:
@SpringBootApplication
@Slf4j
public class DemoApplication{
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@Bean
ApplicationRunner runner(HeadProperties headConfig) {
return arg -> log.info("head config:{}", headConfig);
}
}
下面是错误信息:
APPLICATION FAILED TO START
***************************
Description:
Failed to bind properties under 'head.pay-type' to com.example.demo.HeadProperties$PayType:
Property: head.pay-type
Value: 金币
Origin: class path resource [application.yml] - 2:12
Reason: failed to convert java.lang.String to com.example.demo.HeadProperties$PayType (caused by java.lang.IllegalArgumentException: No enum constant com.example.demo.HeadProperties.PayType.金币)
Action:
Update your application's configuration. The following values are valid:
DIAMOND
GOLD
VIP_FREE
我尝试注入各种转换器,如下面的一个到容器,但它仍然没有工作。
@Component
public class PayTypeConverter implements Converter<String, HeadProperties.PayType> {
@Override
public HeadProperties.PayType convert(String source) {
return HeadProperties.PayType.fromAlias(source);
}
}
@Component
public class PayTypeConverter implements Converter<String, Enum<HeadProperties.PayType>> {
@Override
public Enum<HeadProperties.PayType> convert(String source) {
return HeadProperties.PayType.fromAlias(source);
}
}
如何满足这个要求?
用于@ConfigurationProperties
绑定的转换器需要一个特殊的限定符来告诉Spring它们将用于该目的。
存在此-@ConfigurationPropertiesBinding
的注释。Javadoc格式如下:
因此,所需要做的就是将注释添加到转换器中,然后Spring将在绑定过程中使用它:用于配置@ConfigurationProperties绑定所需的bean的限定符(例如Converters)。
@Component
@ConfigurationPropertiesBinding
public class PayTypeConverter implements Converter<String, HeadProperties.PayType> {
@Override
public HeadProperties.PayType convert(String source) {
return HeadProperties.PayType.fromAlias(source);
}
}
然后产生预期的输出:
head config:HeadProperties(payType=GOLD, cast=10)
还有一个小注意事项,在编写自定义转换器时,要注意返回null不会触发错误(假设没有配置其他措施来防止这种情况)。这意味着与开箱即用的枚举转换器不同,如果找不到匹配的枚举,您的自定义转换器不会产生错误。您可以通过抛出异常而不是返回null来解决这个问题。