Skip to content
Spring Boot sb core 4 min read

Auto-Configuration

Auto-configuration is the feature that lets Spring Boot wire up a working application from almost nothing: add spring-boot-starter-web and you get an embedded Tomcat, a DispatcherServlet, JSON serialization, and sensible defaults — without writing a single @Bean. This page explains how that machinery works and how to inspect and override it.

How @EnableAutoConfiguration works

Auto-configuration is triggered by @EnableAutoConfiguration. You rarely write it directly because the meta-annotation @SpringBootApplication already includes it:

@SpringBootApplication // = @Configuration + @ComponentScan + @EnableAutoConfiguration
public class StoreApplication {
    public static void main(String[] args) {
        SpringApplication.run(StoreApplication.class, args);
    }
}

At startup, @EnableAutoConfiguration asks Spring Boot to find every candidate auto-configuration class on the classpath and apply it. Each candidate is itself a @Configuration class guarded by conditional annotations, so it only contributes beans when its conditions match. The result: configuration appears as a side effect of the dependencies (the starters) you put on the classpath.

Where candidates are declared

Spring Boot finds candidates by reading a resource file packaged in every autoconfigure jar:

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

This is a plain-text file with one fully-qualified class name per line:

org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration

Note: This .imports file is the Spring Boot 2.7+ / 3.x mechanism. It replaced the older approach of listing classes under the org.springframework.boot.autoconfigure.EnableAutoConfiguration key inside META-INF/spring.factories. In Spring Boot 3.x the spring.factories form for auto-configuration has been removed, so any custom auto-config must use the .imports file.

Each class is annotated with @AutoConfiguration (the 3.x stereotype that specializes @Configuration and supports ordering attributes):

@AutoConfiguration
@ConditionalOnClass(ObjectMapper.class)
public class JacksonAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean
    public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
        return builder.build();
    }
}

The condition evaluation report

To see exactly which auto-configurations matched and which were rejected, start the app with --debug:

java -jar store.jar --debug
# or with the Maven plugin:
./mvnw spring-boot:run -Dspring-boot.run.arguments=--debug

This prints the condition evaluation report, grouped into positive and negative matches:

============================
CONDITIONS EVALUATION REPORT
============================

Positive matches:
-----------------
   DataSourceAutoConfiguration matched:
      - @ConditionalOnClass found required class 'javax.sql.DataSource' (OnClassCondition)

   JacksonAutoConfiguration#objectMapper matched:
      - @ConditionalOnMissingBean (types: ObjectMapper) did not find any beans (OnBeanCondition)

Negative matches:
-----------------
   ActiveMQAutoConfiguration:
      Did not match:
         - @ConditionalOnClass did not find required class
           'jakarta.jms.ConnectionFactory' (OnClassCondition)

   MongoAutoConfiguration:
      Did not match:
         - @ConditionalOnClass did not find required class
           'com.mongodb.client.MongoClient' (OnClassCondition)

Read it as the answer to “why is (or isn’t) this bean here?” A positive match means the class/bean was applied; a negative match lists the specific condition that failed. This is the fastest way to debug missing or unexpected beans.

Tip: Setting debug=true in application.properties produces the same report. The report is logged once at startup; it does not change which beans are created — it only explains the decisions.

Excluding auto-configurations

Sometimes a starter pulls in an auto-config you do not want. There are two ways to exclude it.

1. The exclude attribute on @SpringBootApplication (or @EnableAutoConfiguration):

@SpringBootApplication(exclude = {
    DataSourceAutoConfiguration.class,
    HibernateJpaAutoConfiguration.class
})
public class StoreApplication {
    public static void main(String[] args) {
        SpringApplication.run(StoreApplication.class, args);
    }
}

Use excludeName with a string when the class is not on the compile classpath.

2. The spring.autoconfigure.exclude property — handy because it can be set per environment or profile:

spring.autoconfigure.exclude=\
  org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
  org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration
spring:
  autoconfigure:
    exclude:
      - org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
ApproachScopeBest when
exclude attributeCompile-time, always appliedThe class is on the classpath and never wanted
excludeName attributeSame, but string-basedThe class may be absent at compile time
spring.autoconfigure.excludePer-environment via configYou want to exclude only in some profiles

Warning: Excluding an auto-configuration like DataSourceAutoConfiguration while a JDBC starter is still on the classpath means you must supply that infrastructure yourself, or related beans (repositories, JdbcTemplate) will fail to wire. Exclude with intent, and confirm the result in the --debug report.

Override, don’t fight

Because most auto-config beans are guarded by @ConditionalOnMissingBean, the cleanest way to change behavior is usually to define your own bean rather than exclude the whole class. Your bean is registered first, the auto-config’s default backs off, and the rest of the auto-configuration keeps working.

Best Practices

  • Let starters drive auto-configuration; add a dependency rather than hand-wiring infrastructure beans.
  • Use --debug (or debug=true) early when a bean is missing or duplicated — the report names the exact condition.
  • Prefer overriding a single bean over excluding an entire auto-configuration class.
  • When you must exclude, prefer the @SpringBootApplication(exclude = ...) attribute for permanent removals and spring.autoconfigure.exclude for per-profile removals.
  • For custom auto-config, register classes via AutoConfiguration.imports, never the removed spring.factories key.
Last updated June 13, 2026
Was this helpful?