Condition Annotations
You almost always want to include one or more @Conditional
annotations on your auto-configuration class.
The @ConditionalOnMissingBean
annotation is one common example that is used to allow developers to override auto-configuration if they are not happy with your defaults.
Spring Boot includes a number of @Conditional
annotations that you can reuse in your own code by annotating @Configuration
classes or individual @Bean
methods.
These annotations include:
Class Conditions
The @ConditionalOnClass
and @ConditionalOnMissingClass
annotations let @Configuration
classes be included based on the presence or absence of specific classes.
Due to the fact that annotation metadata is parsed by using ASM, you can use the value
attribute to refer to the real class, even though that class might not actually appear on the running application classpath.
You can also use the name
attribute if you prefer to specify the class name by using a String
value.
This mechanism does not apply the same way to @Bean
methods where typically the return type is the target of the condition: before the condition on the method applies, the JVM will have loaded the class and potentially processed method references which will fail if the class is not present.
To handle this scenario, a separate @Configuration
class can be used to isolate the condition, as shown in the following example:
-
Java
-
Kotlin
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@AutoConfiguration
// Some conditions ...
public class MyAutoConfiguration {
// Auto-configured beans ...
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(SomeService.class)
public static class SomeServiceConfiguration {
@Bean
@ConditionalOnMissingBean
public SomeService someService() {
return new SomeService();
}
}
}
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
@Configuration(proxyBeanMethods = false)
// Some conditions ...
class MyAutoConfiguration {
// Auto-configured beans ...
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(SomeService::class)
class SomeServiceConfiguration {
@Bean
@ConditionalOnMissingBean
fun someService(): SomeService {
return SomeService()
}
}
}
If you use @ConditionalOnClass or @ConditionalOnMissingClass as a part of a meta-annotation to compose your own composed annotations, you must use name as referring to the class in such a case is not handled.
|
Bean Conditions
The @ConditionalOnBean
and @ConditionalOnMissingBean
annotations let a bean be included based on the presence or absence of specific beans.
You can use the value
attribute to specify beans by type or name
to specify beans by name.
The search
attribute lets you limit the ApplicationContext
hierarchy that should be considered when searching for beans.
When placed on a @Bean
method, the target type defaults to the return type of the method, as shown in the following example:
-
Java
-
Kotlin
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
@AutoConfiguration
public class MyAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public SomeService someService() {
return new SomeService();
}
}
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
@Configuration(proxyBeanMethods = false)
class MyAutoConfiguration {
@Bean
@ConditionalOnMissingBean
fun someService(): SomeService {
return SomeService()
}
}
In the preceding example, the someService
bean is going to be created if no bean of type SomeService
is already contained in the ApplicationContext
.
You need to be very careful about the order in which bean definitions are added, as these conditions are evaluated based on what has been processed so far.
For this reason, we recommend using only @ConditionalOnBean and @ConditionalOnMissingBean annotations on auto-configuration classes (since these are guaranteed to load after any user-defined bean definitions have been added).
|
@ConditionalOnBean and @ConditionalOnMissingBean do not prevent @Configuration classes from being created.
The only difference between using these conditions at the class level and marking each contained @Bean method with the annotation is that the former prevents registration of the @Configuration class as a bean if the condition does not match.
|
When declaring a @Bean method, provide as much type information as possible in the method’s return type.
For example, if your bean’s concrete class implements an interface the bean method’s return type should be the concrete class and not the interface.
Providing as much type information as possible in @Bean methods is particularly important when using bean conditions as their evaluation can only rely upon to type information that is available in the method signature.
|
Property Conditions
The @ConditionalOnProperty
annotation lets configuration be included based on a Spring Environment property.
Use the prefix
and name
attributes to specify the property that should be checked.
By default, any property that exists and is not equal to false
is matched.
You can also create more advanced checks by using the havingValue
and matchIfMissing
attributes.
Resource Conditions
The @ConditionalOnResource
annotation lets configuration be included only when a specific resource is present.
Resources can be specified by using the usual Spring conventions, as shown in the following example: file:/home/user/test.dat
.
Web Application Conditions
The @ConditionalOnWebApplication
and @ConditionalOnNotWebApplication
annotations let configuration be included depending on whether the application is a “web application”.
A servlet-based web application is any application that uses a Spring WebApplicationContext
, defines a session
scope, or has a ConfigurableWebEnvironment
.
A reactive web application is any application that uses a ReactiveWebApplicationContext
, or has a ConfigurableReactiveWebEnvironment
.
The @ConditionalOnWarDeployment
annotation lets configuration be included depending on whether the application is a traditional WAR application that is deployed to a container.
This condition will not match for applications that are run with an embedded server.
SpEL Expression Conditions
The @ConditionalOnExpression
annotation lets configuration be included based on the result of a SpEL expression.
Referencing a bean in the expression will cause that bean to be initialized very early in context refresh processing. As a result, the bean won’t be eligible for post-processing (such as configuration properties binding) and its state may be incomplete. |