我希望使用spring配置来动态配置不同对象(形状)的列表。应用程序的每个部署都会使列表发生很大变化,有时总共有一个形状,有时在其他形状中有许多相同形状的变体。
预期配置的一个示例如下所示:
app.shapes:
- type: Circle
radius: 3
colors:
- fill: red
border: green
- type: Rectangle
length: 4
width: 2
- type: Circle
radius: 5
colors:
- fill: blue
border: black
- type: Triangle
base: 5
height: 2
到目前为止,我的代码是这样的:
@Slf4j
@SpringBootApplication
public class ConfigListShapesApplication {
@Autowired
private ShapesConfig shapesConfig;
public static void main(String[] args) {
SpringApplication.run(ConfigListShapesApplication.class, args);
}
@PostConstruct
public void logResults() {
log.debug("We have {} shapes configured", shapesConfig.getShapes().size());
for(Shape shape : shapesConfig.getShapes()) {
log.debug("Shape is of type {} and class is instance of {}",
shape.getType(), shape.getClass().getSimpleName());
}
}
@Data
@Component
@ConfigurationProperties(prefix="app")
public class ShapesConfig {
private List<Shape> shapes;
}
@Data
public class Shape {
private String type;
}
@Data
public class Circle extends Shape {
private Integer radius;
private Colors colors;
}
@Data
public class Rectangle extends Shape {
private Integer length;
private Integer width;
private Colors colors;
}
@Data
public class Triangle extends Shape {
private Integer base;
private Integer height;
}
@Data
public class Colors {
private String fill;
private String border;
}
}
每个形状都可以有自己的结构,但是对它来说最有意义。
使用我现在的代码,当我尝试运行它时,会出现以下错误:
***************************
APPLICATION FAILED TO START
***************************
Description:
Binding to target [Bindable@3b152928 type = java.util.List<com.example.configlistshapes.ConfigListShapesApplication$Shape>, value = 'provided', annotations = array<Annotation>[[empty]]] failed:
Property: app.shapes[0].colors[0].border
Value: green
Origin: class path resource [application.yml] - 6:17
Reason: The elements [app.shapes[0].colors[0].border, ....repeat lots...] were left unbound.
Property: app.shapes[0].colors[0].fill
Value: red
Origin: class path resource [application.yml] - 5:15
Reason: The elements [app.shapes[0].colors[0].border ....repeat lots...] were left unbound.
Property: app.shapes[0].radius
Value: 3
.... many more
我看过spring属性转换文档,但它看起来像是转换单个属性的指南。我想我正在研究某种转换,以获得一个配置块(每个形状),然后根据类型创建正确的对象。
我熟悉 @JsonTypeInfo
以及 @JsonSubTypes
在使用jackson和json负载时,可能会有一些动态结构化的json,但是我似乎不知道如何为spring配置做类似的事情。
如果有帮助的话,我已经创建了一个github项目,它可以被拉下来轻松地运行这个mre。
1条答案
按热度按时间wvt8vs2t1#
spring无法知道要示例化哪个特定类,它只会假设您需要一个示例
Shape
.你得到的错误仅仅是由于你忘记声明
Shape
分类为static
.如果你真的想保留配置的多态性,你必须这样做:
记住创建所有嵌套的配置类
static
添加ShapeFactory
,能够根据类型确定应示例化哪种形状,例如:在配置类中添加缺少的构造函数。如果你想要
ShapeFactory.draw
方法来构建带有一行程序的对象,您必须添加专门定制的构造函数。否则,可以使用默认构造函数构建对象并逐个设置属性。关于前者:编辑主配置
ShapesConfig
分类如下:所有形状现在都可以通过
shapesConfig.getActualShapes()
.