00:00

Spring Boot Auto-Configuration

Add one dependency to a Spring Boot project, start it, and a web server, a JSON converter or a database connection pool simply appears, without a single line of setup code. The feature behind this is auto-configuration, and it is the main reason Spring Boot applications need so little configuration.

This tutorial explains what auto-configuration does, how it decides what to create, how to change or switch off its choices, how to see exactly what it did, and how to write your own.

1. What Is Auto-Configuration?

Auto-configuration is Spring Boot’s ability to create and set up beans for you, based on three things:

  • The libraries on your classpath, which come from your dependencies.
  • The beans you have already defined yourself.
  • The properties you have set, for example in application.properties.

In one sentence: add a library, and Spring Boot configures it with sensible defaults, unless you have configured it yourself.

For example, adding spring-boot-starter-web leads Spring Boot to configure:

What gets configuredWhat it does
Embedded Tomcat serverListens for HTTP requests on port 8080
DispatcherServletRoutes each request to the right controller method
Jackson ObjectMapperConverts Java objects to and from JSON
HTTP message convertersRead request bodies and write response bodies
Error handlingProvides the default /error endpoint

2. Why Auto-Configuration Matters

Here is what connecting to a database looked like without auto-configuration. You had to build the connection pool yourself:

DatabaseConfig.java (without auto-configuration)
@Configuration
public class DatabaseConfig {

    @Bean
    public DataSource dataSource() {
        HikariConfig config = new HikariConfig();
        config.setJdbcUrl("jdbc:postgresql://localhost:5432/shop");
        config.setUsername("shop_user");
        config.setPassword("secret");
        config.setMaximumPoolSize(10);
        return new HikariDataSource(config);
    }

    @Bean
    public JdbcTemplate jdbcTemplate(DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }

    // ... plus a transaction manager, and more for JPA
}

With auto-configuration, that whole class disappears. You provide only the values that are specific to your application:

application.properties
spring.datasource.url=jdbc:postgresql://localhost:5432/shop
spring.datasource.username=shop_user
spring.datasource.password=secret

Spring Boot creates the connection pool, the JdbcTemplate and the transaction manager for you. Less code also means fewer places for mistakes, and the defaults follow good practice.

3. How Auto-Configuration Works, Step by Step

  1. Your application starts, and @SpringBootApplication switches on auto-configuration.
  2. Spring Boot first registers your own beans, found through component scanning.
  3. It then reads the list of candidate auto-configuration classes shipped inside the Spring Boot JARs, more than a hundred of them.
  4. For each candidate, it checks its conditions: Is a certain library present? Is a property set? Has the developer already defined this bean?
  5. Only the candidates whose conditions all pass are applied, and their beans are created.
  6. Your application starts with your beans plus the matching auto-configured ones.

Because your own beans are registered first, auto-configuration can see them and step back. That is how your configuration always wins.

4. @SpringBootApplication and @EnableAutoConfiguration

Every Spring Boot application starts from a class annotated with @SpringBootApplication:

ShopApplication.java
@SpringBootApplication
public class ShopApplication {

    public static void main(String[] args) {
        SpringApplication.run(ShopApplication.class, args);
    }
}

@SpringBootApplication is a shortcut for three annotations:

AnnotationRole
@SpringBootConfigurationMarks this as the main configuration class (a special form of @Configuration)
@ComponentScanFinds your own classes, such as controllers and services, in this package and below
@EnableAutoConfigurationSwitches auto-configuration on; this is the key one

You rarely need to write @EnableAutoConfiguration yourself, because @SpringBootApplication already includes it.

5. Where Auto-Configuration Classes Come From

Spring Boot does not scan for auto-configuration classes. Instead, each JAR lists its candidates in a plain text file:

Spring Boot versionFile that lists auto-configuration classes
2.6 and olderMETA-INF/spring.factories
2.7Either file (the new one was introduced; the old one still worked)
3.0 and laterMETA-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

The newer file simply contains one fully qualified class name per line:

AutoConfiguration.imports
com.example.audit.autoconfigure.AuditAutoConfiguration
com.example.audit.autoconfigure.AuditWebAutoConfiguration

Spring Boot’s own list lives in the spring-boot-autoconfigure JAR and includes classes such as DataSourceAutoConfiguration, WebMvcAutoConfiguration, JacksonAutoConfiguration and SecurityAutoConfiguration.

6. Inside an Auto-Configuration Class

An auto-configuration class is an ordinary configuration class with conditions attached. This simplified example shows the typical pattern Spring Boot uses:

SimpleDataSourceAutoConfiguration.java (simplified example)
// 1. Only if Hikari is on the classpath
@AutoConfiguration
@ConditionalOnClass(HikariDataSource.class)
@EnableConfigurationProperties(DataSourceProperties.class)
public class SimpleDataSourceAutoConfiguration {

    // 2. Only if you have not defined a DataSource yourself
    @Bean
    @ConditionalOnMissingBean(DataSource.class)
    public DataSource dataSource(DataSourceProperties properties) {
        // 3. Use the values from spring.datasource.*
        HikariDataSource dataSource = new HikariDataSource();
        dataSource.setJdbcUrl(properties.getUrl());
        dataSource.setUsername(properties.getUsername());
        dataSource.setPassword(properties.getPassword());
        return dataSource;
    }
}

Read it like a set of rules:

  1. If the Hikari library is not on the classpath, skip the whole class.
  2. If you already defined a DataSource bean, skip this method and use yours.
  3. Otherwise, create a DataSource using the values from spring.datasource.*.

Spring Boot’s real DataSourceAutoConfiguration follows the same idea, with more cases. Classes are marked with @AutoConfiguration, introduced in Spring Boot 2.7; older code used @Configuration.

7. Conditional Annotations

Conditions are what make auto-configuration smart. Each one asks a yes-or-no question before a class or bean is applied:

AnnotationApplies when...Example use
@ConditionalOnClassA class is on the classpathConfigure Jackson only if Jackson is present
@ConditionalOnMissingClassA class is not on the classpathFall back to a simpler option
@ConditionalOnBeanA bean of a type already existsConfigure a JdbcTemplate only if a DataSource exists
@ConditionalOnMissingBeanNo bean of that type exists yetCreate a default unless you defined your own
@ConditionalOnPropertyA property has a certain valueA feature switch such as audit.enabled=true
@ConditionalOnWebApplicationThe app is a web applicationConfigure web-only beans
@ConditionalOnNotWebApplicationThe app is not a web applicationConfigure beans for command-line tools
@ConditionalOnResourceA file exists on the classpathLoad settings only if a config file is present
@ConditionalOnSingleCandidateExactly one bean of a type exists, or one is primaryPick the only DataSource automatically
@ConditionalOnJavaRunning on a certain Java versionUse a newer Java feature when available
@ConditionalOnExpressionA SpEL expression is trueComplex rules combining several properties

You can use the same annotations in your own configuration classes. For example, enable a feature only when a property says so:

NotificationConfig.java
@Configuration
public class NotificationConfig {

    @Bean
    @ConditionalOnProperty(name = "shop.notifications.sms.enabled", havingValue = "true")
    public SmsSender smsSender() {
        return new TwilioSmsSender();
    }

    @Bean
    @ConditionalOnMissingBean(SmsSender.class)
    public SmsSender noOpSmsSender() {
        return message -> { /* SMS disabled: do nothing */ };
    }
}

8. Customizing with Properties

The simplest way to change auto-configured behavior is a property. Most auto-configured beans read their settings from application.properties:

application.properties
# Web server
server.port=9090
server.servlet.context-path=/shop

# Connection pool tuning
spring.datasource.hikari.maximum-pool-size=20
# Hikari timeouts are in milliseconds
spring.datasource.hikari.connection-timeout=5000

# JSON output
spring.jackson.serialization.indent-output=true
spring.jackson.default-property-inclusion=non_null

Always try a property first. It keeps all the benefits of auto-configuration and changes only what you need. Your IDE can suggest the available property names as you type.

9. Overriding with Your Own Bean

When a property is not enough, define the bean yourself. Because auto-configured beans use @ConditionalOnMissingBean, Spring Boot sees yours and does not create its own:

DataSourceConfig.java
@Configuration
public class DataSourceConfig {

    @Bean
    public DataSource dataSource(Environment env) {
        HikariDataSource dataSource = new HikariDataSource();
        dataSource.setJdbcUrl(env.getProperty("shop.db.url"));
        dataSource.setUsername(env.getProperty("shop.db.user"));
        dataSource.setPassword(env.getProperty("shop.db.password"));
        dataSource.setPoolName("shop-pool");
        return dataSource;
    }
}

Only the DataSource is replaced. Everything that depends on it, such as JdbcTemplate and the transaction manager, is still auto-configured, and now uses your bean.

10. Excluding an Auto-Configuration

To switch off an auto-configuration completely, exclude it. This is useful when a library is on the classpath but you do not want Spring Boot to configure it:

ShopApplication.java
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class ShopApplication {

    public static void main(String[] args) {
        SpringApplication.run(ShopApplication.class, args);
    }
}

Or exclude it with a property, which lets you do it for one profile only:

application-demo.properties
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
ApproachWhen to use it
Set a propertyYou want the auto-configured bean with different settings (try this first)
Define your own beanYou need full control over one bean, but want the rest auto-configured
Exclude the auto-configurationYou do not want that feature configured at all

11. Seeing What Was Applied

Auto-configuration never has to be a mystery. Start the application with --debug, or set debug=true, and Spring Boot prints a conditions evaluation report:

Terminal
java -jar target/shop.jar --debug
Console (shortened)
============================
CONDITIONS EVALUATION REPORT
============================

Positive matches:
-----------------

   DispatcherServletAutoConfiguration matched:
      - @ConditionalOnClass found required class 'org.springframework.web.servlet.DispatcherServlet'
      - found 'session' scope (OnWebApplicationCondition)

Negative matches:
-----------------

   MongoAutoConfiguration:
      Did not match:
         - @ConditionalOnClass did not find required class 'com.mongodb.client.MongoClient'
SectionMeaning
Positive matchesAuto-configurations that were applied, and why
Negative matchesAuto-configurations that were skipped, and which condition failed
ExclusionsAuto-configurations you excluded on purpose
Unconditional classesConfigurations applied without any condition

In a running application, Spring Boot Actuator shows the same report at /actuator/conditions, once you expose that endpoint. See the Spring Boot Actuator tutorial for setup.

12. Writing Your Own Auto-Configuration

Your own libraries can configure themselves too, just like Spring Boot’s. Imagine a shared audit library used by many services in your company. Instead of every service wiring it up by hand, the library configures itself when it is added as a dependency.

12.1 The properties

AuditProperties.java
package com.example.audit.autoconfigure;

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties(prefix = "company.audit")
public record AuditProperties(
        boolean enabled,
        String applicationName
) {
    public AuditProperties {
        if (applicationName == null) {
            applicationName = "unknown-service";
        }
    }
}

12.2 The auto-configuration class

AuditAutoConfiguration.java
package com.example.audit.autoconfigure;

import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;

@AutoConfiguration
@EnableConfigurationProperties(AuditProperties.class)
@ConditionalOnProperty(prefix = "company.audit", name = "enabled", havingValue = "true", matchIfMissing = true)
public class AuditAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean
    public AuditLogger auditLogger(AuditProperties properties) {
        return new AuditLogger(properties.applicationName());
    }
}

12.3 Register it

Create this file in the library’s src/main/resources folder:

META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
com.example.audit.autoconfigure.AuditAutoConfiguration

12.4 Use it in an application

A service now only adds the dependency and, optionally, a property. The AuditLogger bean is ready to inject:

application.properties
company.audit.application-name=order-service
OrderService.java
@Service
public class OrderService {

    private final AuditLogger auditLogger;

    public OrderService(AuditLogger auditLogger) { // provided by the library
        this.auditLogger = auditLogger;
    }

    public void cancel(Long orderId) {
        // ... cancel the order
        auditLogger.log("Order " + orderId + " cancelled");
    }
}

Setting company.audit.enabled=false switches the whole library off, and defining your own AuditLogger bean replaces the default one, exactly like Spring Boot’s own auto-configurations.

13. Ordering Auto-Configurations

Some auto-configurations depend on others. For example, an audit configuration that writes to the database needs the DataSource to be configured first. Declare the order on @AutoConfiguration:

AuditJdbcAutoConfiguration.java
@AutoConfiguration(after = DataSourceAutoConfiguration.class)
@ConditionalOnBean(DataSource.class)
public class AuditJdbcAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean
    public AuditStore auditStore(DataSource dataSource) {
        return new JdbcAuditStore(dataSource);
    }
}

The after attribute guarantees that the DataSource conditions are evaluated first, so @ConditionalOnBean(DataSource.class) sees the result. There are also before and afterName/beforeName attributes, the last two taking class names as strings.

14. Testing Auto-Configuration

Spring Boot provides ApplicationContextRunner for testing auto-configurations. It starts a tiny application context in milliseconds, and lets you check which beans exist under different conditions:

AuditAutoConfigurationTest.java
class AuditAutoConfigurationTest {

    private final ApplicationContextRunner runner = new ApplicationContextRunner()
            .withConfiguration(AutoConfigurations.of(AuditAutoConfiguration.class));

    @Test
    void createsAuditLoggerByDefault() {
        runner.run(context -> assertThat(context).hasSingleBean(AuditLogger.class));
    }

    @Test
    void canBeSwitchedOffWithAProperty() {
        runner.withPropertyValues("company.audit.enabled=false")
              .run(context -> assertThat(context).doesNotHaveBean(AuditLogger.class));
    }

    @Test
    void backsOffWhenUserDefinesTheirOwnBean() {
        runner.withUserConfiguration(CustomLoggerConfig.class)
              .run(context -> assertThat(context.getBean(AuditLogger.class))
                      .isSameAs(context.getBean("customAuditLogger")));
    }

    @Configuration
    static class CustomLoggerConfig {
        @Bean
        AuditLogger customAuditLogger() {
            return new AuditLogger("custom");
        }
    }
}

These three tests cover the three promises every good auto-configuration makes: it works by default, it can be switched off, and it steps back for the user’s own bean.

15. Starters vs Auto-Configuration

Starters and auto-configuration are often mentioned together, but they do different jobs:

StarterAuto-configuration
What it isA dependency that bundles librariesCode that creates and configures beans
JobPuts the right libraries on the classpathReacts to those libraries and sets them up
ContainsMostly just a pom.xmlConfiguration classes with conditions
Examplespring-boot-starter-webWebMvcAutoConfiguration

They work as a team: the starter brings the libraries, and auto-configuration notices them and configures them. Read more about starters in the Spring Boot Introduction.

16. Common Mistakes to Avoid

MistakeWhat goes wrongFix
Excluding an auto-configuration when a property would doYou lose all its other useful defaultsTry a property or your own bean first
Guessing why a bean is missingHours of trial and errorRun with --debug and read the report
Putting your auto-configuration class in a scanned packageIt is applied as normal configuration, ignoring the intended orderKeep it outside component-scan packages and list it in the .imports file
Forgetting @ConditionalOnMissingBean in your own auto-configurationUsers cannot replace your beanAdd it to every bean users might want to override
Using @ConditionalOnBean in a normal @Configuration classThe result depends on bean registration order and may be wrongUse it only in auto-configuration classes, with proper ordering
Adding starters you do not needUnwanted features are configured and startup is slowerRemove unused dependencies

17. Summary

Auto-configuration is a set of ordinary configuration classes, listed inside Spring Boot’s JARs and guarded by conditions. At startup, Spring Boot checks each condition, such as which libraries are present, which beans you defined and which properties you set, and applies only the configurations that fit. You stay in control: change settings with properties, replace single beans with your own, exclude whole configurations, and use the conditions report to see exactly what happened.

Interview one-liner: Spring Boot auto-configuration creates beans automatically based on the classpath, existing beans and properties, using conditional annotations, and steps back whenever the developer provides their own configuration.

18. Frequently Asked Questions (FAQ)

Q1. Is auto-configuration some kind of magic?

No. Auto-configuration classes are ordinary Spring configuration classes with @Bean methods, the same kind you write yourself. The only difference is that they carry conditions, and Spring Boot loads them from a list inside its JARs instead of finding them by component scanning.

You can open any of them in your IDE. Search for a class such as JacksonAutoConfiguration and read exactly what it creates and under which conditions.

Q2. Why didn’t Spring Boot create a bean I expected?

One of its conditions failed. The most common reasons:

  • A dependency is missing, so @ConditionalOnClass fails.
  • You defined a bean of the same type, so @ConditionalOnMissingBean makes Spring Boot step back.
  • A property switched it off, or a required property is missing.
  • It was excluded, on the annotation or in spring.autoconfigure.exclude.

Do not guess: run with --debug and search the Negative matches section of the report for the auto-configuration you expected. It names the exact condition that failed.

Q3. Does auto-configuration slow down application startup?

Only a little. Most conditions are cheap checks, such as “is this class present?”, and Spring Boot pre-filters candidates using metadata generated at build time, so most non-matching classes are skipped quickly.

The bigger cost is the beans that do get created. To keep startup fast:

  • Remove starters and libraries you do not use.
  • Exclude auto-configurations for features you do not need.
  • For the fastest startup, use Spring’s ahead-of-time (AOT) processing and GraalVM native images.
Q4. What is the difference between @Configuration and @AutoConfiguration?
@Configuration@AutoConfiguration
Written byApplication developersLibrary and framework authors
Found byComponent scanningThe AutoConfiguration.imports file
AppliedFirst, as user configurationAfter user configuration, so it can step back
Ordering attributesNobefore and after

In your application code, use @Configuration. Use @AutoConfiguration only when writing a reusable library that should configure itself.

Q5. Why must my auto-configuration classes not be picked up by component scanning?

If a component scan finds your auto-configuration class, Spring treats it as normal user configuration. It is then processed too early, before other auto-configurations, so:

  • Conditions like @ConditionalOnBean may see the wrong set of beans.
  • before and after ordering is ignored.
  • Applications cannot exclude it with spring.autoconfigure.exclude in the usual way.

Put auto-configuration classes in their own package, for example com.example.audit.autoconfigure, outside the application’s scanned packages, and register them only through the .imports file.

Q6. Why is @ConditionalOnBean risky in normal configuration classes?

@ConditionalOnBean only sees beans that have been registered so far. In ordinary @Configuration classes, the order in which classes are processed is not guaranteed, so the bean you check for might be registered a moment later. The condition then fails, even though the bean exists.

Inside auto-configuration it is reliable, because auto-configurations run after all user configuration and can declare their order with after = .... In application code, prefer @ConditionalOnProperty, or inject an ObjectProvider and check it at runtime:

@Bean
public ReportService reportService(ObjectProvider<EmailSender> emailSender) {
    return new ReportService(emailSender.getIfAvailable()); // null if no EmailSender bean
}
Q7. How does Spring Boot choose between Tomcat and Jetty?

By what is on the classpath. The web starter includes Tomcat, so Tomcat’s auto-configuration matches. To switch, exclude Tomcat and add Jetty:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jetty</artifactId>
</dependency>

No code changes are needed: @ConditionalOnClass now finds Jetty instead of Tomcat, and the matching server is configured.

Q8. I have both H2 and a MySQL driver. Which database does Spring Boot use?

It depends on whether you set a URL:

  • No spring.datasource.url: Spring Boot starts an embedded database, H2 here, because it can run without any connection details.
  • URL set to a MySQL address: Spring Boot connects to MySQL, and H2 is simply unused.

A common setup keeps H2 for tests and local experiments, and sets the MySQL URL in a profile:

# application-prod.properties
spring.datasource.url=jdbc:mysql://db.internal:3306/shop
spring.datasource.username=shop
spring.datasource.password=${DB_PASSWORD}
Q9. Can I turn off auto-configuration completely?

Yes: replace @SpringBootApplication with @Configuration and @ComponentScan, leaving out @EnableAutoConfiguration. You must then define every bean yourself, including the web server and the JSON converter.

This is rarely a good idea, because you lose most of what Spring Boot offers. A middle way is @ImportAutoConfiguration, which applies only the auto-configurations you list:

@Configuration
@ComponentScan
@ImportAutoConfiguration({
        JacksonAutoConfiguration.class,
        DataSourceAutoConfiguration.class
})
public class MinimalApplication { }
Q10. How does auto-configuration work in tests?
Test annotationAuto-configuration applied
@SpringBootTestEverything, as in the real application
@WebMvcTestOnly web-related parts: MVC, JSON, validation
@DataJpaTestOnly JPA, the DataSource and transactions
ApplicationContextRunnerOnly what you pass in, for testing auto-configuration itself

Slice tests are faster because they apply only a small, relevant set of auto-configurations. If a slice test needs one extra feature, add it with @ImportAutoConfiguration.

Q11. Why does Spring Boot print a generated security password at startup?

When Spring Security is on the classpath and you have not configured any users, its auto-configuration creates one default user named user, with a random password printed in the log:

Using generated security password: 3f1c2a9e-8b7d-4c55-9e21-6a0d7f4b2e18

This keeps a new application from being accidentally open. It disappears as soon as you define your own security setup, for example a UserDetailsService bean, or configure a login provider such as OAuth2. Never rely on this default user in production.

Q12. How do my properties reach auto-configured beans?

Through @ConfigurationProperties classes. Each auto-configuration has one, bound to a prefix, for example spring.datasource or server. Spring Boot fills it from your properties and environment variables, and the auto-configuration reads from it when creating beans.

Name matching is flexible. All of these set the same value:

server.max-http-request-header-size=16KB      (application.properties)
SERVER_MAXHTTPREQUESTHEADERSIZE=16KB         (environment variable)
--server.max-http-request-header-size=16KB    (command-line argument)

Library JARs also ship metadata describing every property, which is how your IDE can auto-complete names and show descriptions.

Q13. What happened to spring.factories for auto-configuration?

Older Spring Boot versions listed auto-configuration classes in META-INF/spring.factories. Spring Boot 2.7 introduced the dedicated AutoConfiguration.imports file, and Spring Boot 3.0 stopped reading auto-configurations from spring.factories.

If a library you upgraded silently stops configuring itself on Spring Boot 3, this is a likely cause. Move its entries into:

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

spring.factories still exists for other purposes, such as registering listeners, but not for auto-configuration.

Q14. How should I name my own starter and auto-configuration modules?

Names starting with spring-boot are reserved for official Spring Boot modules. For your own, put your project name first:

ModuleExample nameContains
Auto-configurationaudit-spring-boot-autoconfigureThe @AutoConfiguration classes and properties
Starteraudit-spring-boot-starterJust dependencies: the library plus the auto-configure module

For small libraries, a single module containing both is fine. Separating them helps when users want the auto-configuration without all the starter’s optional dependencies.

Q15. What is the difference between auto-configuration and component scanning?
Component scanningAuto-configuration
FindsYour classes: @Component, @Service, @ControllerLibrary configuration from .imports files
Where it looksYour application’s packagesEvery JAR on the classpath
ConditionsUsually noneAlways, so it only applies when it fits
RunsFirstAfterwards, so it can adapt to your beans

@SpringBootApplication switches on both: component scanning for your code, and auto-configuration for everything else.

Q16. Can I adjust an auto-configured bean without replacing it entirely?

Yes. Many auto-configurations accept customizer beans. Spring Boot creates the bean as usual and then passes it through your customizer, so you keep all the defaults and change only one detail:

@Configuration
public class WebServerConfig {

    // Adjust the auto-configured web server instead of replacing it
    @Bean
    public WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> serverCustomizer() {
        return factory -> factory.setPort(9090);
    }

    // Add to the auto-configured RestClient.Builder used across the app
    @Bean
    public RestClientCustomizer defaultHeaders() {
        return builder -> builder.defaultHeader("X-Client", "shop-service");
    }
}

Customizers are a good middle ground between setting a property and defining a whole bean yourself.

Q17. Does the order of dependencies in pom.xml affect auto-configuration?

No. Auto-configuration depends on which libraries are present, not on the order they are listed in. Order between auto-configurations is controlled only by their before and after settings.

What does matter is which version of a library ends up on the classpath. Let Spring Boot manage versions, and avoid overriding them unless you have a specific reason.

Q18. How many auto-configurations does Spring Boot have, and are they all applied?

Spring Boot ships well over a hundred auto-configuration classes, covering web servers, databases, messaging, caching, security, monitoring and more.

Only a fraction are applied in any given application. A simple web service might use a few dozen, because most conditions fail: no MongoDB driver means no MongoDB configuration, and so on. The --debug report shows the exact split for your application.

Q19. How can I see which settings the auto-configured beans are using?

Spring Boot Actuator has endpoints that show what is configured in a running application:

EndpointShows
/actuator/configpropsEvery @ConfigurationProperties bean and its current values, with secrets masked
/actuator/envEach property and the source it came from, such as a file or an environment variable
/actuator/beansEvery bean, its type and its dependencies
/actuator/conditionsWhy each auto-configuration was or was not applied
management.endpoints.web.exposure.include=health,configprops,env,beans,conditions

These endpoints reveal internal details, so expose them only in development or behind security.

Q20. Does auto-configuration work with GraalVM native images?

Yes, with one important difference. For native images, Spring’s ahead-of-time (AOT) processing evaluates the conditions at build time and generates plain code for the result.

This means the decisions are fixed when you build:

  • The classpath cannot change at runtime.
  • Conditions on properties are evaluated with the build-time values, so switching a feature on later with a property may not work as expected.
  • Profiles that change which beans exist should be decided at build time too.

In return, the application starts in a fraction of the time, because no conditions are evaluated at startup.