PrepZone Logo
PrepZone

How Auto-Configuration Works

Conditional beans, AutoConfiguration.imports, and how Boot configures itself.

Why this matters

  • Understanding auto-config explains why adding a starter suddenly gives you a DataSource, Jackson, or SecurityFilterChain without writing config.
  • Debugging "bean not found" or "bean already defined" conflicts requires knowing which auto-config class created the bean.
  • Writing custom starters for shared BookStore libraries depends on the same conditional mechanism.

How auto-config loads

Boot 3.x reads candidate classes from:

Java
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

Each line is a fully qualified @Configuration class. AutoConfigurationImportSelector loads them after your own @Configuration classes, so your beans take precedence.

Example entry for the web starter:

Java
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration

Conditional evaluation

Every auto-config class uses @Conditional annotations:

Java
@AutoConfiguration
@ConditionalOnClass(DataSource.class)
@ConditionalOnProperty(name = "spring.datasource.url")
@EnableConfigurationProperties(DataSourceProperties.class)
public class DataSourceAutoConfiguration {
    @Bean
    @ConditionalOnMissingBean
    public DataSource dataSource(DataSourceProperties props) {
        return DataSourceBuilder.create()
            .url(props.getUrl())
            .username(props.getUsername())
            .password(props.getPassword())
            .build();
    }
}

Beans register only when:

DataSource auto-config conditions

  • DataSource class is on the classpath (JPA starter present)
  • spring.datasource.url property is set
  • No user-defined DataSource @Bean already exists
Classpath scanFind @AutoConfiguration classes
@Conditional checksOnClass, OnBean, OnProperty
Register beansOnly if conditions pass
Boot checks classpath and existing beans before creating defaults.

Common @ConditionalOn* annotations

  • @ConditionalOnClass — Classpath contains the named class.
  • @ConditionalOnMissingBean — No bean of this type registered yet (user override wins).
  • @ConditionalOnProperty — Property matches expected value.
  • @ConditionalOnWebApplication — Running as a servlet web app.
  • @ConditionalOnExpression — SpEL expression evaluates to true.

User overrides auto-config

Your @Bean replaces auto-configured beans because of @ConditionalOnMissingBean:

Java
@Configuration
public class TestDataSourceConfig {
    @Bean
    public DataSource dataSource() {
        return new EmbeddedDatabaseBuilder()
            .setType(EmbeddedDatabaseType.H2)
            .build();
    }
}

Boot's DataSourceAutoConfiguration sees an existing DataSource and backs off.

Inspecting what matched

Enable the auto-config report:

Java
debug: true
# or
logging:
  level:
    org.springframework.boot.autoconfigure: DEBUG

Startup logs list positive and negative matches:

Java
DataSourceAutoConfiguration matched:
  - @ConditionalOnClass found required class 'javax.sql.DataSource'
  - @ConditionalOnProperty (spring.datasource.url) matched

RedisAutoConfiguration did not match:
  - @ConditionalOnClass did not find required class 'org.springframework.data.redis.core.RedisOperations'

Auto-config ordering

@AutoConfigureBefore and @AutoConfigureAfter control relative order:

Java
@AutoConfiguration(after = DataSourceAutoConfiguration.class)
public class JpaRepositoriesAutoConfiguration { ... }

JPA repositories need a DataSource first — ordering prevents startup race conditions.

Disabling auto-config

Globally:

Java
@SpringBootApplication(exclude = {
    SecurityAutoConfiguration.class,
    ManagementWebSecurityAutoConfiguration.class
})

Via properties:

Java
spring:
  autoconfigure:
    exclude:
      - org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration

Use sparingly — excluding security in production BookStore is dangerous.

The @AutoConfiguration annotation

Boot 3 replaced @Configuration on auto-config classes with @AutoConfiguration for clearer semantics and ordering support. Custom starters should use:

Java
@AutoConfiguration
@ConditionalOnClass(BookStoreClient.class)
public class BookStoreClientAutoConfiguration {
    @Bean
    @ConditionalOnMissingBean
    public BookStoreClient bookStoreClient(BookStoreProperties props) {
        return new BookStoreClient(props);
    }
}

Register in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports.

Quick recall

Everything you need if you only revisit this box.

  • Auto-config classes load from META-INF/spring/...AutoConfiguration.imports.
  • Each class uses @ConditionalOn* to register beans only when appropriate.
  • @ConditionalOnMissingBean lets your @Bean definitions override defaults.
  • debug: true prints positive and negative auto-config matches at startup.
  • @AutoConfigureAfter ensures beans like DataSource exist before JPA repos.
  • Custom starters use @AutoConfiguration + conditions + the imports file.

Test yourself

Answer these before moving on — recall is what makes it stick.