Spring 4.0 new features: @Conditional annotation introduced in detail

  • 2020-10-23 20:57:36
  • OfStack

preface

Having recently studied spring, we will take a moment to summarize what we have learned. In this article, we will touch on a new feature of spring 4: the @Conditional annotation. In previous versions of spring, you dealt with conditions only in the following two ways:

Before version 3.1, you will need to use spring expression language At the 3.1 release, profiles was introduced to handle conditions.

Let's take a look at each of the above to understand the @Conditional annotation that comes with spring 4.

Spring Expression Language(SPeL)

The 3-element identifier of SPeL (ES24en-ES25en-ES26en) can be used to express conditional statements in the spring configuration file.


<bean id="flag">
 <constructor-arg value="#{systemProperties['system.propery.flag'] ?: false }" />
</bean>
<bean id="bean">
 <property name="property" value="#{ flag ? 'yes' : 'no' }"/>
</bean>

This PROPERTY of bean depends on the value of flag, which is injected using an external property, giving bean dynamic capabilities.

Using Profiles

This was introduced in spring 3.1. Use it like this.


<!-- default configuration - will be loaded if no profile is specified -->
<!-- This will only work if it's put at the end of the configuration file -->
<!-- so no bean definitions after that -->
<beans profile="default">
  <import resource="classpath:default.xml" />
</beans>
<!-- some other profile -->
<beans profile="otherProfile">
 <import resource="classpath:other-profile.xml" />
</beans>

Use the @Conditional annotation on spring 4

Now introduce the @Conditional annotation. The official documentation states that "components can only be registered if all specified conditions are met." The main use is to add a series of constraints when creating bean.

The Conditional interface is declared as follows:


@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE, ElementType.METHOD)
public @interface Conditional{
 Class <!--?extends Condition-->[] value();
}

So the @Conditional annotation is used as follows

Type level, which can be used on either the @Component or @Configuration classes Prototype level, which can be used on other custom annotations Method level, which can be used on the @Bean method

If one @Configuration class USES @ES64en, all @Bean methods and @ES66en associative classes are affected


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);
}

Here is an example


public class SystemPropertyCondition implements Condition {
 @Override
 public boolean matches(ConditionContext context, AnnotatedTypeMetadata   metadata) {
  return (System.getProperty("flag") != null);
 }
}

class SystemPropertyAbsentCondition implements Condition {
 @Override
 public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
  return (System.getProperty("flag") == null);
 }
}

Here we have two classes: SystemPropertyCondition and SystemPropertyAbsentCondtion. Both classes implement the Condition interface. The overridden method returns 1 Boolean based on the attribute flag.

Now we define two classes, one for the positive condition and one for the negative condition:


@Bean
@Conditional(SystemPropertyCondition.class)
public SampleService service1() {
 return new SampleServiceImpl1();
}

@Bean
@Conditional(SystemPropertyAbsentCondition.class)
public SampleService service2() {
 return new SampleServiceImpl2();
}

The profiles mentioned above has been modified with the conditional prototype annotation.

conclusion

This article introduces the conditianal annotation for spring 4. Note that the condition annotation is not inherited. If a parent class USES the conditional annotation, a child class does not own conditions. It will help you to get a better understanding if you try the examples above.


Related articles: