How does Spring Boot's auto-configuration mechanism work?

9 minadvancedauto-configurationconditionalspring-boot

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 @Bean definition override an auto-configured default — if you define your own DataSource bean, 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.

Related Resources