Java @列表或数组的条件属性?

Java @列表或数组的条件属性?,java,spring,spring-boot,properties,Java,Spring,Spring Boot,Properties,我使用的是Spring Boot 1.4.3@AutoConfiguration,其中我根据用户指定的属性自动创建bean。用户可以指定服务数组,其中名称和版本是必填字段: service[0].name=myServiceA service[0].version=1.0 service[1].name=myServiceB service[1].version=1.2 ... 如果用户忘记仅在一个服务上指定必填字段,我想退出,不创建任何bean。我可以用@ConditionalOnPro

我使用的是Spring Boot 1.4.3
@AutoConfiguration
,其中我根据用户指定的属性自动创建bean。用户可以指定服务数组,其中名称版本是必填字段:

service[0].name=myServiceA
service[0].version=1.0

service[1].name=myServiceB
service[1].version=1.2

...
如果用户忘记仅在一个服务上指定必填字段,我想退出,不创建任何bean。我可以用
@ConditionalOnProperty
实现这一点吗?我想要像这样的东西:

@Configuration
@ConditionalOnProperty({"service[i].name", "service[i].version"})
class AutoConfigureServices {
....
} 

这是我创建的自定义
条件。它需要一些改进才能更通用(即不是硬编码字符串),但对我来说效果很好

为了使用,我用
@Conditional(RequiredRepeatablePropertiesCondition.class)

公共类RequiredRepeatablePropertiesCondition扩展了SpringBootCondition{
私有静态最终记录器Logger=LoggerFactory.getLogger(RequiredRepeatablePropertiesCondition.class.getName());
公共静态最终字符串[]必需的\u键={
“my.services[i].version”,
“my.services[i].name”
};
@凌驾
public ConditionOutput GetMatchOutput(ConditionContext上下文,AnnotatedTypeMetadata元数据){
List missingProperties=new ArrayList();
RelaxedPropertySolver解析器=新的RelaxedPropertySolver(context.getEnvironment());
Map services=resolver.getsubperties(“my.services”);
if(services.size()==0){
missingProperties.addAll(Arrays.asList(必需的_键));
返回GetConditionOutput(缺少属性);
}
//收集要检查的索引:[0]、[1]、[3]等
Pattern p=Pattern.compile(\\[(\\d+\\\]);
Set uniqueindex=new HashSet();
for(字符串键:services.keySet()){
匹配器m=p.Matcher(键);
if(m.find()){
添加(m组(1));
}
}
//循环每个索引并检查所需的道具
uniqueIndexes.forEach(索引->{
for(字符串genericKey:必需的\u键){
字符串multiServiceKey=genericKey.replace(“[i]”,“[“+index+”]);
if(!resolver.containsProperty(multiServiceKey)){
missingProperties.add(multiServiceKey);
}
}
});
返回GetConditionOutput(缺少属性);
}
私有条件结果GetConditionOutput(列出缺少的属性){
if(missingProperties.isEmpty()){
返回ConditionOutput.match(ConditionMessage.forCondition(RequiredRepeatablePropertiesCondition.class.getCanonicalName())
.发现(“财产”、“财产”)
.项(数组.asList(必需的_键));
}
返回conditionoutput.noMatch(
ConditionMessage.forCondition(RequiredRepeatablePropertiesCondition.class.getCanonicalName())
.didNotFind(“财产”、“财产”)
.项目(丢失属性)
);
}
}

老问题,但我希望我的回答对Spring2.x有所帮助: 多亏了@Brian,我查阅了迁移指南,在那里我受到了示例代码的启发。此代码适用于我:

final List<String> services = Binder.get(context.getEnvironment()).bind("my.services", List.class).orElse(null);

好了,继续玩吧:-D

下面是我对这个问题的看法,在Spring自动配置中使用自定义条件。与@Strumbels的建议有些相似,但更易于重用

@条件注释在应用程序启动的早期执行。属性源已加载,但尚未创建configurationProperties bean。但是,我们可以通过自己将属性绑定到JavaPOJO来解决这个问题

首先,我介绍一个功能接口,它使我们能够定义任何自定义逻辑检查属性是否存在。在您的情况下,此方法将负责检查属性列表是否为空/null以及其中的所有项是否有效

公共界面选项属性{
布尔isPresent();
}
现在,让我们创建一个注释,该注释将使用Spring
@Conditional
进行元注释,并允许我们定义自定义参数
prefix
表示属性名称空间,
targetClass
表示属性应映射到的配置属性模型类

@Target({ElementType.TYPE,ElementType.METHOD})
@保留(RetentionPolicy.RUNTIME)
@记录
@条件(onConfiguration PropertiesCondition.class)
public@interface ConditionalOnConfigurationProperties{
字符串前缀();
Class targetClass=mergedAnnotation.getClass(“targetClass”);
//类型前提条件
如果(!OptionalProperties.class.isAssignableFrom(targetClass)){
return conditionoutput.noMatch(“目标类型不实现OptionalProperties接口”);
}
//此解决方案的关键是将属性绑定到JavaPOJO
objectbean=Binder.get(context.getEnvironment()).bind(前缀,targetClass).orElse(null);
//如果属性根本不存在,则返回不匹配
if(bean==null){
返回ConditionOutput.noMatch(“将属性绑定到目标类型导致空值”);
}
OptionalProperties道具=(OptionalProperties)bean;
//从OptionalProperties接口执行方法
//检查条件是否匹配
//可以以类型安全的方式使用属性值包括任何自定义逻辑
if(props.isPresent()){
返回conditionoutput.match();
}否则{
返回conditionoutput.noMatch(“属性不存在”);
}
}
}
现在,您应该创建自己的配置属性类来实现
OptionalProperties
接口

@ConfigurationProperties(“your.property.prefix”)
@构造绑定
公共类YourConfigurationProperties实现OptionalProperties{
//服务是表示名称和版本的POJO
final List<String> services = Binder.get(context.getEnvironment()).bind("my.services", List.class).orElse(null);
final Services services = Binder.get(context.getEnvironment()).bind("my.services", Services.class).orElse(null);