How does Spring Boot's auto-configuration mechanism work?
Quick Answer
Auto-configuration classes are ordinary @Configuration classes, listed in a file under META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports on the classpath, each guarded by @Conditional-family annotations (@ConditionalOnClass, @ConditionalOnMissingBean, @ConditionalOnProperty, etc.). At startup, Spring Boot loads every listed auto-configuration class but only actually applies each one's bean definitions if its conditions are satisfied — e.g., a DataSource auto-configuration only activates if a JDBC driver is on the classpath and no DataSource bean has already been defined by the application.
Detailed Answer
Auto-configuration classes are just regular @Configuration classes — nothing magical about their structure — bundled inside Spring Boot's spring-boot-autoconfigure module (and inside third-party starter JARs). What makes them "auto" is two things working together:
1. Discovery: Spring Boot loads a list of candidate auto-configuration classes from a file at META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports on the classpath (this replaced the older spring.factories-based mechanism in Spring Boot 2.7+/3.x). Every listed class is a candidate to be evaluated — not necessarily applied.
2. Conditional activation: each auto-configuration class is guarded by one or more @Conditional-family annotations, so it only actually contributes bean definitions if its conditions hold:
@Configuration
@ConditionalOnClass(DataSource.class) // only if a DataSource class is on the classpath
@ConditionalOnMissingBean(DataSource.class) // only if the app hasn't already defined its own DataSource
@EnableConfigurationProperties(DataSourceProperties.class)
public class DataSourceAutoConfiguration {
@Bean
public DataSource dataSource(DataSourceProperties properties) {
return properties.initializeDataSourceBuilder().build();
}
}
Common condition annotations:
@ConditionalOnClass/@ConditionalOnMissingClass— is a given class present/absent on the classpath (used to detect "is this dependency actually included").@ConditionalOnBean/@ConditionalOnMissingBean— does a bean of a given type already exist in the context (this is exactly what lets your own@Beandefinition override an auto-configured default — if you define your ownDataSourcebean, the auto-configured one backs off).@ConditionalOnProperty— is a specific configuration property set (and optionally, to a specific value).@ConditionalOnWebApplication— is this a web application context at all.
This design is exactly why Spring Boot feels "magical" but remains fully overridable: adding spring-boot-starter-data-jpa to the classpath makes JPA-related conditions become true, activating a cascade of auto-configuration; defining your own equivalent bean explicitly makes the corresponding @ConditionalOnMissingBean condition false, causing Boot's default to quietly step aside in favor of yours.
@EnableAutoConfiguration(exclude = ...) (or the spring.autoconfigure.exclude property) lets you explicitly disable a specific auto-configuration class you don't want, even if its conditions would otherwise be satisfied.