Spring 4 @Conditional Annotation

As part of my series on the new features in Spring Framework, version 4, I’d like to present how to use the new Condition interface and @Conditional annotation.

@Conditional annotation

Spring 4 is introducing a new feature called Conditional – So it’s time to implement Spring 4 Conditional checking by using @Conditional annotation. This annotation with programmatic condition implementation. It can react to rich context. @Profile annotation support now simply a ProfileCondition implementation class of conditional annotation.

 

Spring 4 @Conditional Annotation

@ImageSource-Slideshare.net

There are times when you would like the creation and dependency injection of a bean to depend on circumstances. Those circumstance could be what operating system your application is running in, or what application server it finds itself on. Bean configuration may also depend on what version of Java is available, the value of a system property/environmental variable, or whether your application is running in dev, test, stage, or production. For these and a host of other reasons, you may want to conditionalize the instantiation and wiring of your Spring beans.

@Retention(value=RUNTIME)
@Target(value={TYPE,METHOD})
public @interface Conditional

Indicates that a component is is only eligible for registration when all specified conditions match.
A condition is any state that can be determined pro-grammatically immediately before the bean is due to be created

The @Conditional annotation may be used in any of the following ways:

  • as a type-level annotation on any class directly or indirectly annotated with @Component, including @Configuration classes.
  • as a meta-annotation, for the purpose of composing custom stereotype annotations.
  • as a method-level annotation on any @Bean method

If a @Configuration class is marked with @Conditional, all of the @Bean methods and @Import annotations associated with that class will be subject to the conditions.

The condition interface is as follows:

public interface Condition{
/** Determine if the condition matches.
* @param context the condition context
* @param metadata meta-data of the {@link AnnotationMetadata class} or
* {@link Method method} being checked.
* @return {@code true} if the condition matches and the component can be registered
* or {@code false} to veto registration.
*/
boolean matches(ConditionContext context, AnnotatedTypeMedata metadata);
}

SPRING 4.0 CONDITIONAL BEAN CONFIGURATION-

Spring 4 adds a new @Conditional annotation that allows for a similar conditionalized configuration, but one that does not require a profile. Using the operating system example again, you would need to create two classes that implement the Spring Condition interface. This interface requires the implementation of a matches( ) method. The matches( ) method checks for a condition and returns a boolean indicating whether that condition is met.

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
 
public class LinuxCondition implements Condition{
 
  @Override
  public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
    return context.getEnvironment().getProperty("os.name").contains("Linux");  }
}
import org.springframework.context.annotation.Condition; 
import org.springframework.context.annotation.ConditionContext; 
import org.springframework.core.type.AnnotatedTypeMetadata; 
 
public class WindowsCondition implements Condition{
 
  @Override 
  public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
    return context.getEnvironment().getProperty("os.name").contains("Windows");
  }
}

The ConditionContext parameter to matches( ) provides access to the environment, container, class loader, etc. that the condition may use to make its boolean-producing determination. The AnnotatedTypeMetadata parameter to matches( ) provides access to the method on which the @Conditional using the Condition is applied to.

With the conditions in place, now annotate your Configuration bean methods with @Conditional and the condition checking class as a parameter. Note how both methods in the Configuration return an EmailService implementation named “emailerService”. However, only one of these methods will get called by the container and create the emailerService based on the conditions provided through @Conditional.

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
 
@Configuration
public class MyConfiguration {
 
  @Bean(name="emailerService")
  @Conditional(WindowsCondition.class)
  public EmailService windowsEmailerService(){
      return new WindowsEmailService();
  }
 
  @Bean(name="emailerService")
  @Conditional(LinuxCondition.class)
  public EmailService linuxEmailerService(){
    return new LinuxEmailService();
  }
}

The example here uses the conditions for the creation of just one bean. However, the conditions serve as a more reusable mechanism, which could be used to conditionalize all sorts of beans.

 

<<Previous <<   || Index ||   >>Next >>

 

Previous
Next

No Responses

  1. Pingback: A Simple Example of Using Spring Aspect Oriented Programming to Log the Beginning and End of All Methods in All Classes in a Package – Watne Household Site November 24, 2020