Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

@ConditionalOnProperty for multi-valued properies

Is there any way to use @ConditionalOnProperty annotation based on multi-valued property?

Spring configuration:

@Bean
@ConditionalOnProperty(name = "prop", havingValue = "a")
public SomeBean bean1() {
    return new SomeBean1();
}

@Bean
@ConditionalOnProperty(name = "prop", havingValue = "b")
public SomeBean bean2() {
    return new SomeBean2();
}

and application.yaml

prop: 
 - a
 - b

I expect that both beans: bean1 and bean2 will be registered in the spring context, but no one from them isn't registered. Is there any way to do it?

like image 275
Maksim Prabarshchuk Avatar asked Jun 22 '16 13:06

Maksim Prabarshchuk


1 Answers

It looks like @ConditionalOnProperty haven't multivalued properies. In spring environment they are presented as

prop[0]=a
prop[1]=b

My solution is to make my own @Conditional extension, that is able to work with multivalued properies. Here is the example.

Annotation:

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Documented
@Conditional(OnPropertyCondition.class)
public @interface ConditionalOnProperty2 {
    String name();
    String value();
}

Condition:

class OnPropertyCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        String name = attribute(metadata, "name");
        String value = attribute(metadata, "value");

        String searchName = name;
        String property = property(context, searchName);
        int i = 0;
        do {
            if (value.equals(property)) return true;
            searchName = name + '[' + i++ + ']';
        } while ((property = property(context, searchName)) != null);
        return false;
    }

    private String attribute(AnnotatedTypeMetadata metadata, String name) {
        return (String) metadata.getAnnotationAttributes(ConditionalOnProperty2.class.getName()).get(name);
    }

    private String property(ConditionContext context, String name) {
        return context.getEnvironment().getProperty(name);
    }
}

Usage:

 @Bean
 @ConditionalOnProperty2(name = "prop", havingValue = "a")
 public SomeBean bean1() {
     return new SomeBean1();
 }

 @Bean
 @ConditionalOnProperty2(name = "prop", havingValue = "b")
 public SomeBean bean2() {
     return new SomeBean2();
 }
like image 170
Maksim Prabarshchuk Avatar answered Nov 11 '22 06:11

Maksim Prabarshchuk