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.spring[email protected]2641e737: 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.