Close

Spring - @Bean conditional registration

[Updated: Dec 8, 2016, Created: Sep 6, 2016]

Spring 4, introduced a new annotation @Conditional, which is meant to be used on @Bean methods or with @Component classes (if we are using @ComponentScan), and that includes @Configuration classes as well.


The purpose of this annotation is to enable/disable target beans from being registered based on some condition. These conditions are applied at the time of the container startup.


The annotation @Conditional requires value() element as array of the classes implementing the Condition interface (also introduced in Spring 4).



How it works?




@Conditional vs @Profile

The use of @Conditional and Condition is is similar to selecting different profiles using @Profile but is more flexible because the conditions are specified in Java code rather than using some pre defined property flag or some system property.

Spring uses @Conditional on @Profile definition as meta annotation. That means @Conditional concept is on lower level than that of @Profile.

Spring profiles have been around since 3.1 and they were refactored in 4.0 to take advantage of this new way of applying conditions on bean registration. Here's the code source snippets of @Profile and ProfileCondition

.....
@Conditional(ProfileCondition.class)
public @interface Profile {
  ....
}
class ProfileCondition implements Condition {

 @Override
 public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
  if (context.getEnvironment() != null) {
   MultiValueMap<String, Object> attrs =
                          metadata.getAllAnnotationAttributes(
                                                       Profile.class.getName());
  if (attrs != null) {
   for (Object value : attrs.get("value")) {
    if (context.getEnvironment().acceptsProfiles(
                                              ((String[]) value))) {
     return true;
    }
   }
   return false;
  }
 }
 return true;
 }
}

What is ConditionContext?

ConditionContext is the first parameter of ProfileCondition#matches method. This facade interface was introduced to work with Condition. We can query container related information via this interface. e.g. we can get instance of ConfigurableListableBeanFactory, Environment, BeanDefinitionRegistry etc.



What is AnnotatedTypeMetadata?

AnnotatedTypeMetadata helps retrieving information about specified annotation type used on underlying element i.e. the same element annotated with @Conditional: the method with @Bean or class with @Component or @Configuration.

This meta data helper can get us the attributes of annotations like @Bean, @Component, @Lazy, @Scope etc, used on the same method or class.

Example Project

This example project demonstrates how we can register a bean selectively depending on the underlying locale of the machine this app is running on.



Dependencies and Technologies Used:

  • Spring Context 4.3.2.RELEASE: Spring Context.
  • JDK 1.8
  • Maven 3.0.4

Bean Conditional Selection Example Select All Download
  • bean-conditional-registration
    • src
      • main
        • java
          • com
            • logicbig
              • example

See Also