问题描述
我使用的是Spring Boot 1.4.3 @AutoConfiguration
,其中我根据用户指定的属性自动创建bean.用户可以指定一组服务,其中名称和版本是必填字段:
I'm using Spring Boot 1.4.3 @AutoConfiguration
where I create beans automatically based on properties user specifies. User can specify an array of services, where name and version are required fields:
service[0].name=myServiceA
service[0].version=1.0
service[1].name=myServiceB
service[1].version=1.2
...
如果用户忘记仅在一项服务上也指定了必填字段,那么我想回退而不创建任何bean.我可以用@ConditionalOnProperty
完成吗?我想要类似的东西:
If the user forgets to specify a required field on even just one service, I want to back-off and not create any beans. Can I accomplish this with @ConditionalOnProperty
? I want something like:
@Configuration
@ConditionalOnProperty({"service[i].name", "service[i].version"})
class AutoConfigureServices {
....
}
推荐答案
这是我创建的自定义Condition
.需要进行一些改进以使其更通用(即,不对字符串进行硬编码),但对我来说非常有用.
This is the custom Condition
I created. It needs some polishing to be more generic (ie not hardcoding strings), but worked great for me.
要使用,我用@Conditional(RequiredRepeatablePropertiesCondition.class)
public class RequiredRepeatablePropertiesCondition extends SpringBootCondition {
private static final Logger LOGGER = LoggerFactory.getLogger(RequiredRepeatablePropertiesCondition.class.getName());
public static final String[] REQUIRED_KEYS = {
"my.services[i].version",
"my.services[i].name"
};
@Override
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
List<String> missingProperties = new ArrayList<>();
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(context.getEnvironment());
Map<String, Object> services = resolver.getSubProperties("my.services");
if (services.size() == 0) {
missingProperties.addAll(Arrays.asList(REQUIRED_KEYS));
return getConditionOutcome(missingProperties);
}
//gather indexes to check: [0], [1], [3], etc
Pattern p = Pattern.compile("\\[(\\d+)\\]");
Set<String> uniqueIndexes = new HashSet<String>();
for (String key : services.keySet()) {
Matcher m = p.matcher(key);
if (m.find()) {
uniqueIndexes.add(m.group(1));
}
}
//loop each index and check required props
uniqueIndexes.forEach(index -> {
for (String genericKey : REQUIRED_KEYS) {
String multiServiceKey = genericKey.replace("[i]", "[" + index + "]");
if (!resolver.containsProperty(multiServiceKey)) {
missingProperties.add(multiServiceKey);
}
}
});
return getConditionOutcome(missingProperties);
}
private ConditionOutcome getConditionOutcome(List<String> missingProperties) {
if (missingProperties.isEmpty()) {
return ConditionOutcome.match(ConditionMessage.forCondition(RequiredRepeatablePropertiesCondition.class.getCanonicalName())
.found("property", "properties")
.items(Arrays.asList(REQUIRED_KEYS)));
}
return ConditionOutcome.noMatch(
ConditionMessage.forCondition(RequiredRepeatablePropertiesCondition.class.getCanonicalName())
.didNotFind("property", "properties")
.items(missingProperties)
);
}
}
这篇关于@ConditionalOnProperty用于列表或数组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!