Auto\Configuration vs Configuration
How Does Auto-Configuration Work?
Classpath Scanning: Spring Boot starts by scanning the application’s classpath. This scanning is targeted, looking for specific markers and metadata that suggest configuration details.
spring.factories
File: Central to auto-configuration is the spring.factories
file, located inside the META-INF
directory of jar files, particularly in starter dependencies. This file lists the auto-configuration classes (annotated with @Configuration
) that should be considered.
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.mycorp.libx.autoconfigure.LibXAutoConfiguration,\
com.mycorp.libx.autoconfigure.LibXWebAutoConfiguration
Auto-Configuration Classes: These classes contain conditional annotations (like @ConditionalOnClass
, @ConditionalOnBean
) that dictate when a particular configuration should be applied. They define beans and other settings that configure aspects of the application.
Role of Starter Dependencies
Starters, such as spring-boot-starter-web
or spring-boot-starter-jersey
, are key players in auto-configuration. They bundle together dependencies for a particular technology stack, including the spring.factories
file that directs Spring Boot on what auto-configurations to apply.
Activation of Auto-Configuration
During the application’s startup, Spring Boot processes all spring.factories
files found on the classpath. It evaluates the conditions in the listed auto-configuration classes and applies the configurations as appropriate.
Deep Dive: The Auto-Configuration Process
- Initial Bootstrap: When a Spring Boot application starts, the initial bootstrap process sets up the basic environment, including the default ApplicationContext.
- Processing
spring.factories
: Spring Boot readsspring.factories
files from all jars in the classpath, gathering a list of auto-configuration classes. - Conditional Processing: Each auto-configuration class can have multiple conditional annotations. Spring Boot evaluates these conditions in the context of the current application. For instance,
@ConditionalOnClass
checks if a specific class is in the classpath. - Bean Creation and Configuration: If conditions are met, Spring Boot executes the auto-configuration class, resulting in the creation of beans and other configurations. This includes setting up default properties, initializing web servers (like Tomcat for web applications), configuring data sources, and more.
Customization and Overriding Auto-Configurations
Spring Boot’s auto-configuration is not a rigid process. You can customize or override these auto-configurations in several ways:
- Custom
@Configuration
Classes: You can define your own configuration classes to specify or override beans. - Application Properties: Using
application.properties
orapplication.yml
, you can customize various aspects of the auto-configurations, such as server port, database URLs, etc. - Excluding Auto-Configurations: You can exclude specific auto-configuration classes using the
@EnableAutoConfiguration
annotation with theexclude
attribute.
https://www.devskillbuilder.com/spring-boot-auto-configuration-a-deep-dive-ab886e84fb74
Configuration vs AutoConfiguration
@Configuration
is a spring framework annotation and not strictly bound to spring-boot
. It was introduced when spring started to allow programmatic creation of spring-beans
as to move forward from xml
definitions of beans.
@AutoConfiguration
is a spring-boot
specific annotation not commonly available in spring framework. The reason it exists, is for external providers that cooperate with spring-boot
to be able to mark some classes in some libraries they provide with this annotation as to inform spring-boot
that those classes could be parsed and make some initializations during start up of spring application automatically.
Conditions
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.
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:
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();
}
}
}
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:
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();
}
}
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.
If multiple names are given in the name
attribute, all of the properties have to pass the test for the condition to match.
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
and @ConditionalOnNotWarDeployment
annotations let configuration be included depending on whether the application is a traditional WAR application that is deployed to a servlet container. This condition will not match for applications that are run with an embedded web 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.