Spring Boot读取YAML文件至子类时属性为null,求排查
问题分析与解决方案
你的代码存在基础类结构错误、YAML与Java对象映射不匹配、Spring配置方式不当三类核心问题,以下是具体修正步骤:
1. 修复类实现与构造函数的基础错误
首先,你的LiteralExpression和FunctionExpression未实现Expression接口,且构造函数存在笔误,这是Spring无法识别实例类型的核心原因:
修正后的LiteralExpression
public class LiteralExpression implements Expression { private final String literal; public LiteralExpression(String literal) { this.literal = literal; // 修复原代码中this.value的错误赋值 } @Override public String evaluate() { return literal; } }
修正后的FunctionExpression
public class FunctionExpression implements Expression { private final String name; private final Expression[] params; // 修复构造函数类名写错的问题,以及this.value的错误赋值 public FunctionExpression(String name, Expression... params) { this.name = name; this.params = params; } @Override public String evaluate() { return Functions.getFunction(name).apply( Stream.of(params) .map(Expression::evaluate) .toArray(String[]::new) ); } }
2. 解决多态对象的YAML映射问题
Spring无法自动识别YAML中的literal/function字段对应的具体子类,需要添加类型标识并配置Jackson注解:
修改YAML文件,添加类型标识
expressions: - expression: type: literal literal: hello - expression: type: function name: add params: - expression: type: literal literal: 1 - expression: type: literal literal: 2
给Expression接口添加Jackson多态注解
import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonTypeInfo; @JsonTypeInfo( use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type" // 对应YAML中的type字段 ) @JsonSubTypes({ @JsonSubTypes.Type(value = LiteralExpression.class, name = "literal"), @JsonSubTypes.Type(value = FunctionExpression.class, name = "function") }) public interface Expression { String evaluate(); }
3. 调整Spring配置类与解析方式
你当前用YamlPropertySourceFactory将YAML转成扁平的Properties,会丢失多态结构信息,应改用Spring Boot原生的YAML解析方式:
移除@PropertySource,引入自定义YAML文件
在application.yaml中添加配置,引入你的自定义YAML文件:
spring: config: import: classpath:expressions.yaml
修正配置类,添加包装类匹配YAML结构
由于YAML中每个元素都包含expression键,需要用包装类承接,避免直接用List<Expression>无法匹配结构:
@Component @ConfigurationProperties @NoArgsConstructor @Data public class ProfileConfig { // 修复原类名ProfielConfig的拼写错误 private List<ExpressionWrapper> expressions; // 包装类匹配YAML中的expression键结构 @Data @NoArgsConstructor public static class ExpressionWrapper { private Expression expression; } }
4. 确保构造函数可被Spring实例化
Spring需要无参构造函数或通过@ConstructorBinding指定构造函数,给子类添加Lombok注解:
@AllArgsConstructor // 替代手动写带参构造函数 public class LiteralExpression implements Expression { private final String literal; @Override public String evaluate() { return literal; } }
@AllArgsConstructor public class FunctionExpression implements Expression { private final String name; private final Expression[] params; @Override public String evaluate() { return Functions.getFunction(name).apply( Stream.of(params) .map(Expression::evaluate) .toArray(String[]::new) ); } }
内容的提问来源于stack exchange,提问作者Dalendrion
相关产品推荐
相关产品推荐

