Spring Configuration Condition Example

0

A component gets registered when it is annotated with either @Configuration or @Component. Spring allows one to programatically add a condition, which will be evaluated during the parsing stage as well as bean registration stage, the result of which will decide whether to allow or skip the registration. If the condition fails to match during the parsing stage itself, then the configuration contents will not be parsed further.

Suppose your condition depends on whether certain bean is registered then you need a fine-grained control on when the condition is to be applied. If the condition is applied during parsing phase, then the condition may fail, as the bean the condition is looking out for may not be parsed yet. Using ConfigurationCondition you can differ condition’s evaluation to a later stage when all the configuration classes are parsed.

Condition Example

Let’s first implement Condition which we will improvise later. The condition matches if ‘beanA’ is is already registered.

IfBeanAExistsCondition:

package com.javarticles.spring.annotations;

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;

public class IfBeanAExistsCondition implements Condition {

    public boolean matches(ConditionContext context,
            AnnotatedTypeMetadata metadata) {
        return context.getBeanFactory().containsBeanDefinition("beanA");
    }
}

In the below example, BeanB‘s registration depends on the condition that BeanA is already registered. If we first register BeanA and then BeanB, the condition will pass and you will see even BeanB getting registered but if it is the other way, that is, register BeanB first and then BeanA then the condition will fail..

SpringConditionalAnnotationExample:

package com.javarticles.spring.annotations;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;

public class SpringConditionalAnnotationExample {

    public static void main(String[] args) {
        loadContextAndVerifyBeans(BeanA.class, BeanB.class);
        loadContextAndVerifyBeans(BeanB.class);
        loadContextAndVerifyBeans(BeanB.class, BeanA.class);
    }

    private static void loadContextAndVerifyBeans(Class...classToRegister) {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
        try {
            ctx.register(classToRegister);
            ctx.refresh();
            System.out.println("Has beanA? " + ctx.containsBean("beanA"));
            System.out.println("Has beanB? " + ctx.containsBean("beanB"));
        } finally {
            ctx.close();
        }
    }

    @Configuration("beanA")
    static class BeanA {
    }

    @Configuration("beanB")
    @Conditional(IfBeanAExistsCondition.class)
    static class BeanB {
    }
}

Output:

Jan 30, 2016 9:30:11 PM org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
INFO: Refreshing org.spring[email protected]4783da3f: startup date [Sat Jan 30 21:30:11 IST 2016]; root of context hierarchy
Has beanA? true
Has beanB? true
Jan 30, 2016 9:30:11 PM org.springframework.context.annotation.AnnotationConfigApplicationContext doClose
INFO: Closing org.spring[email protected]4783da3f: startup date [Sat Jan 30 21:30:11 IST 2016]; root of context hierarchy
Jan 30, 2016 9:30:11 PM org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.annotation.Annotat[email protected]: startup date [Sat Jan 30 21:30:11 IST 2016]; root of context hierarchy
Has beanA? false
Has beanB? false
Jan 30, 2016 9:30:11 PM org.springframework.context.annotation.AnnotationConfigApplicationContext doClose
INFO: Closing org.spring[email protected]2641e737: startup date [Sat Jan 30 21:30:11 IST 2016]; root of context hierarchy
Jan 30, 2016 9:30:11 PM org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
INFO: Refreshing org.spring[email protected]df27fae: startup date [Sat Jan 30 21:30:11 IST 2016]; root of context hierarchy
Jan 30, 2016 9:30:11 PM org.springframework.context.annotation.AnnotationConfigApplicationContext doClose
INFO: Closing org.spring[email protected]df27fae: startup date [Sat Jan 30 21:30:11 IST 2016]; root of context hierarchy
Has beanA? true
Has beanB? false

Configuration Condition Example

We will now implement the same condition by implementing the fine-grained ConfigurationCondition. We need to implement getConfigurationPhase() to set the phase when the condition needs to be evaluated, In this case during REGISTER_BEAN phase when the all @Configuration classes are parsed.

IfBeanAExistsConfigurationCondition:

package com.javarticles.spring.annotations;

import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.annotation.ConfigurationCondition;
import org.springframework.core.type.AnnotatedTypeMetadata;

public class IfBeanAExistsConfigurationCondition implements ConfigurationCondition {

    public boolean matches(ConditionContext context,
            AnnotatedTypeMetadata metadata) {
        return context.getBeanFactory().containsBeanDefinition("beanA");
    }

    public ConfigurationPhase getConfigurationPhase() {
        return ConfigurationPhase.REGISTER_BEAN;
    }
}

SpringConfigurationConditionExample:

package com.javarticles.spring.annotations;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;

public class SpringConfigurationConditionExample {

    public static void main(String[] args) {
        loadContextAndVerifyBeans(BeanA.class, BeanB.class);
        loadContextAndVerifyBeans(BeanB.class);
        loadContextAndVerifyBeans(BeanB.class, BeanA.class);
    }

    private static void loadContextAndVerifyBeans(Class<?>...classToRegister) {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
        try {
            ctx.register(classToRegister);
            ctx.refresh();
            System.out.println("Has beanA? " + ctx.containsBean("beanA"));
            System.out.println("Has beanB? " + ctx.containsBean("beanB"));
        } finally {
            ctx.close();
        }
    }

    @Configuration("beanA")
    static class BeanA {
    }

    @Configuration("beanB")
    @Conditional(IfBeanAExistsConfigurationCondition.class)
    static class BeanB {
    }
}

You can see from the output, irrespective of the order in which beans are registered, the condition passes and BeanB gets registered.

Output:

Jan 30, 2016 9:35:06 PM org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
INFO: Refreshing org.spring[email protected]4783da3f: startup date [Sat Jan 30 21:35:06 IST 2016]; root of context hierarchy
Has beanA? true
Has beanB? true
Jan 30, 2016 9:35:06 PM org.springframework.context.annotation.AnnotationConfigApplicationContext doClose
INFO: Closing org.spring[email protected]4783da3f: startup date [Sat Jan 30 21:35:06 IST 2016]; root of context hierarchy
Jan 30, 2016 9:35:06 PM org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
INFO: Refreshing org.spring[email protected]2641e737: startup date [Sat Jan 30 21:35:06 IST 2016]; root of context hierarchy
Has beanA? false
Has beanB? false
Jan 30, 2016 9:35:06 PM org.springframework.context.annotation.AnnotationConfigApplicationContext doClose
INFO: Closing org.spring[email protected]2641e737: startup date [Sat Jan 30 21:35:06 IST 2016]; root of context hierarchy
Jan 30, 2016 9:35:06 PM org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
INFO: Refreshing org.spring[email protected]df27fae: startup date [Sat Jan 30 21:35:06 IST 2016]; root of context hierarchy
Has beanA? true
Has beanB? true
Jan 30, 2016 9:35:06 PM org.springframework.context.annotation.AnnotationConfigApplicationContext doClose
INFO: Closing org.spring[email protected]df27fae: startup date [Sat Jan 30 21:35:06 IST 2016]; root of context hierarchy

Download the source code

This was an example about Configuration Condition.

You can download the source code here: springConfigurationConditionExample.zip
Share.

Comments are closed.