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