如何以多态方式读取application.yml中的配置属性?
解决Spring Boot多态配置属性绑定问题
问题根源
Spring无法自动将字符串类型的"any"转换为Filter接口的实现类,也无法区分何时使用SimpleFilter(对应字符串值)和ComplexFilter(对应嵌套对象)。
解决方案一:自定义Converter + Jackson多态注解
1. 给Filter接口添加Jackson多态注解
修改RootProperties中的Filter接口及实现类,通过Jackson注解让Spring能自动推断类型:
import com.fasterxml.jackson.annotation.JsonSubTypes import com.fasterxml.jackson.annotation.JsonTypeInfo import org.springframework.boot.context.properties.ConfigurationProperties @ConfigurationProperties(prefix = "root") data class RootProperties( var config: Map<String, UserProperty>?, ) { data class UserProperty( var filter: Filter, ) @JsonTypeInfo( use = JsonTypeInfo.Id.DEDUCTION, // 根据字段自动推断类型 defaultImpl = SimpleFilter::class // 默认用SimpleFilter处理字符串转换场景 ) @JsonSubTypes( JsonSubTypes.Type(ComplexFilter::class), JsonSubTypes.Type(SimpleFilter::class) ) interface Filter data class SimpleFilter( var value: String, ) : Filter data class ComplexFilter( var type: TypeFilter, ) : Filter data class TypeFilter( var or: List<String>, ) }
2. 自定义字符串转Filter的Converter
创建Converter组件,将字符串值转换为SimpleFilter实例:
import org.springframework.core.convert.converter.Converter import org.springframework.stereotype.Component @Component class StringToFilterConverter : Converter<String, RootProperties.Filter> { override fun convert(source: String): RootProperties.Filter { return RootProperties.SimpleFilter(source) } }
3. 保持配置类不变
你的RootConfigTest已添加@EnableConfigurationProperties(RootProperties::class),无需额外修改。
解决方案二:调整配置格式(无需修改代码)
如果允许修改application.yml,可以把role2的filter改为对象结构,让Spring自动绑定到SimpleFilter:
root: config: role1: filter: type: or: - type1 - type2 role2: filter: value: any
这种方式不需要自定义Converter,Jackson的多态注解会自动完成类型推断。
验证
启动应用后,rootProperties中role1.filter会是ComplexFilter实例,role2.filter会是SimpleFilter实例,配置绑定成功。
内容的提问来源于stack exchange,提问作者gstackoverflow
相关产品推荐
相关产品推荐

