java - @ConditionalOnProperty 用于列表或数组?

标签 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。我可以使用 @ConditionalOnProperty 完成此操作吗?我想要这样的东西:

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

最佳答案

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

为了使用,我用 @Conditional(RequiredRepeatablePropertiesCondition.class) 注释了我的 Configuration 类

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)
        );
    }
}

关于java - @ConditionalOnProperty 用于列表或数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41916042/

相关文章:

java - 未使用的@param标签的checkstyle_error

java - 使用反射调用字段上的方法

java - 使用构造函数注入(inject)模式对 spring boot 进行集成测试

mysql - Spring Data 1.7.0.RELEASE查询策略报错 "The infrastructure apparently does not support query methods"

java - 使用 Spring Boot 配置 Logback

java - 如何解决 spring-boot 中的 URI 编码问题?

java - 如何授权对我的 GAE REST 服务器的请求?

java - 使用别名参数名称来接受 Url 编码表单数据值

java - spring如何将方法调用解析为bean?

java - 仅修改当前请求的SecurityContext