@ConditionalOnProperty用于列表或数组? [英] @ConditionalOnProperty for lists or arrays?

查看:1263
本文介绍了@ConditionalOnProperty用于列表或数组?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的是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用于列表或数组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆