Spring 4

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.

 

@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
Dinesh Rajput

Dinesh Rajput is the chief editor of a website Dineshonjava, a technical blog dedicated to the Spring and Java technologies. It has a series of articles related to Java technologies. Dinesh has been a Spring enthusiast since 2008 and is a Pivotal Certified Spring Professional, an author of a book Spring 5 Design Pattern, and a blogger. He has more than 10 years of experience with different aspects of Spring and Java design and development. His core expertise lies in the latest version of Spring Framework, Spring Boot, Spring Security, creating REST APIs, Microservice Architecture, Reactive Pattern, Spring AOP, Design Patterns, Struts, Hibernate, Web Services, Spring Batch, Cassandra, MongoDB, and Web Application Design and Architecture. He is currently working as a technology manager at a leading product and web development company. He worked as a developer and tech lead at the Bennett, Coleman & Co. Ltd and was the first developer in his previous company, Paytm. Dinesh is passionate about the latest Java technologies and loves to write technical blogs related to it. He is a very active member of the Java and Spring community on different forums. When it comes to the Spring Framework and Java, Dinesh tops the list!

Share
Published by
Dinesh Rajput

Recent Posts

Strategy Design Patterns using Lambda

Strategy Design Patterns We can easily create a strategy design pattern using lambda. To implement…

2 years ago

Decorator Pattern using Lambda

Decorator Pattern A decorator pattern allows a user to add new functionality to an existing…

2 years ago

Delegating pattern using lambda

Delegating pattern In software engineering, the delegation pattern is an object-oriented design pattern that allows…

2 years ago

Spring Vs Django- Know The Difference Between The Two

Technology has emerged a lot in the last decade, and now we have artificial intelligence;…

2 years ago

TOP 20 MongoDB INTERVIEW QUESTIONS 2022

Managing a database is becoming increasingly complex now due to the vast amount of data…

2 years ago

Scheduler @Scheduled Annotation Spring Boot

Overview In this article, we will explore Spring Scheduler how we could use it by…

3 years ago