@ Conditional and @ ConditionalXXX of spring boot

Keywords: Programming Spring Google REST

The most amazing feature of spring boot should be automatic configuration. Since the moment you introduced spring boot starter XX, spring boot has done a lot of work for us later. Let's talk about how the whole process is organized later. Today we'll take a look at @ Conditional, a key annotation in spring boot that determines whether a bean or configuration class can be injected into a container.

@Conditional -- conditional annotation. Let's look at the definition of this annotation

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {

	/**
	 * All {@link Condition Conditions} that must {@linkplain Condition#matches match}
	 * in order for the component to be registered.
	 */
	Class<? extends Condition>[] value();

}

You can see that this annotation can be used on classes and methods. In general, we do not use this annotation directly, but use @ ConditionalOnXXX (for example, @ ConditionalOnBean). So what's the relationship between @ ConditionalOnXXX and @ Conditional. In fact, @ ConditionalOnXXX mainly uses the derived nature of spring's annotations (no better term has been found for the moment). What is the derivation of annotation? It is that @ ConditionalOnXXX has the characteristics of @ Conditional, but it can have its own unique characteristics.

What condition annotations are provided in spring boot for us to use

Class Conditions

  • @ConditionalOnClass
 @Bean
 @ConditionalOnClass(name = "com.google.gson.Gson")
 public OrderTest orderTest(){
     OrderTest orderTest = new OrderTest();
     System.out.println("Because of the introduction of gson,So initialization");
     return orderTest;
 }

Because the classpath contains the Gson class, it will be initialized. Note the difference between value and name in annotation

  • @ConditionalOnMissingClass
    @Bean
    @ConditionalOnMissingClass(value = "com.google.gson.Gson")
    public OrderTest orderTest2(){
        OrderTest orderTest = new OrderTest();
        System.out.println("Because it wasn't introduced gson,So initialization");
        return orderTest;
    }

Because there is no Gson class in classpath, it will be initialized.

Bean Conditions

  • @ConditionalOnBean
    @Bean
    @ConditionalOnBean(type = {"com.google.gson.Gson"})
    public OrderTest orderTest3(){
        OrderTest orderTest = new OrderTest();
        System.out.println("Because there are gson,So initialization");
        return orderTest;
    }
  • @ConditionalOnMissingBean
    @Bean
    @ConditionalOnMissingBean(type = {"com.google.gson.Gson"})
    public OrderTest orderTest4(){
        OrderTest orderTest = new OrderTest();
        System.out.println("Because there is no container gson,So initialization");
        return orderTest;
    }

Note the difference with Class condition. One is whether the class path contains the other is whether the container contains the other.

Property Conditions

  • @ConditionalOnProperty
    @Bean
    @ConditionalOnProperty(prefix = "test.auto.login",name = "aop",havingValue = "YES")
    public OrderTest orderTest4(){
        OrderTest orderTest = new OrderTest();
        System.out.println("When the property value is equal to YES Only when");
        return orderTest;
    }

Only when test.auto.login.aop=YES in the environment variable is injected. This gives us a lot of operation space. When defining the start component, the user can decide whether to inject it or not.

SpEL Expression Conditions

  • @ConditionalOnExpression
    @Bean
    @ConditionalOnExpression("#{'YES'.equals(environment['test.auto.login.aop'])}")
    public OrderTest orderTest4(){
        OrderTest orderTest = new OrderTest();
        System.out.println("When the property value is equal to YES Only when");
        return orderTest;
    }

More advanced is that this device supports SpEL expressions, in other words, it enables you to support more complex logical judgments

Resource Conditions

It's not often used, so let's not talk about it here

Web Application Conditions

It's not often used. I won't talk about it here

So far as the usage of conditional annotation is concerned, why do we give some values in the conditional annotation, and the framework can help us automatically determine whether we need to inject. We can see the implementation of each annotation

Implementation of various conditional annotations

  • @ConditionalOnClass
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnClassCondition.class) // The point is this
public @interface ConditionalOnClass 
  • @ConditionalOnBean
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnBeanCondition.class)//Here's the key
public @interface ConditionalOnBean 

  • @ConditionalOnExpression
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Documented
@Conditional(OnExpressionCondition.class) //Key logic
public @interface ConditionalOnExpression

The rest will not be listed. Through these three typical annotations, we can see that what really enables conditional annotation is OnXxxx.class. What does this class do next time

Posted by vcv on Tue, 14 Apr 2020 10:38:39 -0700