Home/Learn/Spring Boot/Auto-Configuration

Auto-Configuration

Intermediate
Core & Setup

Spring Boot scans the classpath and conditionally creates beans on your behalf; understanding @EnableAutoConfiguration and spring.factories unlocks deep customisation.

Overview

Auto-configuration is the cornerstone of Spring Boot's "convention over configuration" philosophy. When you add spring-boot-starter-data-jpa to your project, Spring Boot automatically creates a DataSource, EntityManagerFactory, and TransactionManager — without a single explicit @Bean declaration. This works through @EnableAutoConfiguration (included in @SpringBootApplication), which loads hundreds of configuration classes from META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports (Spring Boot 3+) or spring.factories (Spring Boot 2.x). Each class is heavily conditional — it only activates when specific classes, beans, or properties are present. Understanding this mechanism lets you write your own starters, override auto-configured beans, and debug unexpected behaviour efficiently.

How Auto-Configuration Works Internally

At startup, ImportAutoConfigurationImportSelector loads all auto-configuration classes from the imports file. Each class is a @Configuration annotated with @Conditional variants. Spring evaluates every condition before deciding whether to register the beans inside. Two rules are critical:

1. Auto-configuration classes are processed after all user-defined beans — your @Bean definitions always win. 2. @ConditionalOnMissingBean skips the auto-configured bean if you have already registered one of that type.

Java — Spring Boot
// Spring Boot 3 imports file:
// META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration

// Simplified example of DataSourceAutoConfiguration
@AutoConfiguration
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
@ConditionalOnMissingBean(type = "io.r2dbc.spi.ConnectionFactory")
@EnableConfigurationProperties(DataSourceProperties.class)
public class DataSourceAutoConfiguration {

    @Configuration(proxyBeanMethods = false)
    @Conditional(PooledDataSourceCondition.class)
    @ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
    @Import({ DataSourceConfiguration.Hikari.class })
    protected static class PooledDataSourceConfiguration { }
}

Key @Conditional Annotations

@ConditionalOnClass — fires only if the specified class is on the classpath (e.g., DataSource.class). @ConditionalOnMissingBean — skipped if a bean of that type already exists — the primary override mechanism. @ConditionalOnProperty — activates when a property key has a given value (e.g., spring.datasource.url). @ConditionalOnWebApplication — only in a web (Servlet or Reactive) context. @ConditionalOnExpression — complex boolean conditions via Spring EL.

Java / Properties
// Override the auto-configured DataSource with your own
@Configuration
public class MyDataSourceConfig {

    @Bean  // Your bean is registered first => auto-config's @ConditionalOnMissingBean skips it
    public DataSource dataSource(DataSourceProperties props) {
        return DataSourceBuilder.create()
            .url(props.getUrl())
            .username(props.getUsername())
            .password(props.getPassword())
            .driverClassName("com.mysql.cj.jdbc.Driver")
            .build();
    }
}

// Disable auto-config entirely via application.properties
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration

Debugging Auto-Configuration

Start the application with --debug (or debug=true in application.properties) to print the ConditionEvaluationReport. It lists every auto-configuration class, whether it matched, and the exact condition reason — invaluable when a bean is missing or an unexpected bean appears in the context.

Shell
# Run with debug flag
java -jar myapp.jar --debug

# Or set in application.properties
debug=true

# Excerpt from ConditionEvaluationReport output:
# Positive matches:
#   DataSourceAutoConfiguration matched:
#     - @ConditionalOnClass found required classes 'DataSource' (OnClassCondition)
#
# Negative matches:
#   MongoAutoConfiguration:
#     Did not match: @ConditionalOnClass did not find required class
#       'com.mongodb.MongoClient' (OnClassCondition)

Key Points to Remember

  • 1@SpringBootApplication includes @EnableAutoConfiguration which triggers the entire auto-configuration loading mechanism.
  • 2Auto-configuration classes are loaded from META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports (Boot 3) or META-INF/spring.factories (Boot 2).
  • 3@ConditionalOnMissingBean is the primary escape hatch — declare your own @Bean of the same type to override any auto-configured bean.
  • 4User-defined beans are always registered before auto-configured ones, so explicit definitions always win.
  • 5Use the --debug flag to print the ConditionEvaluationReport and understand exactly why each auto-config fired or was skipped.
  • 6Write your own Spring Boot starter by creating a @Configuration class with @Conditional annotations and registering it in the AutoConfiguration.imports file.

Interview Questions

Sign in to ask Aria
1

How does Spring Boot auto-configuration work internally — what loads the configuration classes?

MediumAmazon
2

How do you disable a specific auto-configuration class in Spring Boot?

EasyGoogle
3

What is the difference between @ConditionalOnClass and @ConditionalOnMissingBean?

MediumFlipkart
4

How would you create a custom Spring Boot starter with auto-configuration?

HardNetflix
5

What happens when you define your own DataSource @Bean in a Spring Boot app that already has datasource auto-config?

MediumInfosys

Ask Aria about Auto-Configuration

Your personal AI tutor — ask anything about this concept

Revision Status

Personal Notes

Sign in to save personal notes for this topic.

Discussion

Sign in to join the discussion.

Loading discussion…