@SpringBootApplication

Marks the main class of a Spring Boot application: switches on auto-configuration and component scanning from the package it sits in.

Signature
@SpringBootApplication(exclude = SomeAutoConfiguration.class, scanBasePackages = "com.example")
  • Added in Spring Boot Spring Boot 1.2.0

Parameters

ParameterTypeDescription
$excludeoptionalClass<?>[]= {}Auto-configuration classes that must never be applied.
$excludeNameoptionalString[]= {}Auto-configuration classes to exclude, given by fully qualified name. Useful when the class is not on the classpath at compile time.
$scanBasePackagesoptionalString[]= {}Packages to scan for components instead of the annotated class's own package.
$scanBasePackageClassesoptionalClass<?>[]= {}Type-safe alternative to scanBasePackages: the package of each class is scanned.
$nameGeneratoroptionalClass<? extends BeanNameGenerator>= BeanNameGenerator.class (the default naming)Strategy for naming beans found by scanning.
$proxyBeanMethodsoptionalboolean= trueWhether @Bean methods declared on this class are proxied so that calls between them return the shared bean.

Return value

n/aDeclares the class as the application's primary configuration and turns on auto-configuration and component scanning rooted at the class's package.

Errors

Nothing at compile time. A bad exclude (a class that is not an auto-configuration) fails startup with an IllegalStateException.

Changelog

  • PHP Spring Boot 1.3.0Added scanBasePackages and scanBasePackageClasses.
  • PHP Spring Boot 2.2.0Added proxyBeanMethods.
  • PHP Spring Boot 2.3.0Added nameGenerator.

@SpringBootApplication goes on exactly one class: the one with the main method. It is a shortcut for three annotations: @SpringBootConfiguration (a specialised @Configuration), @EnableAutoConfiguration and @ComponentScan. Together they tell Spring Boot to read your own beans, then add the beans that the starters on the classpath provide, backing off wherever you defined your own.

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

Where the class lives matters

Component scanning starts in the package of the annotated class and walks down into every sub-package. Put the class in the root package, for example com.example.orders, with features below it in com.example.orders.billing and so on. The most common startup surprise is a controller in com.example.api that never registers because the main class sits in com.example.orders, a sibling rather than a parent. No error is raised; the endpoint simply returns 404.

The package also anchors other scanning: Spring Data repositories and JPA entities are found under the same root by default. Moving the main class therefore changes more than you might expect.

Excluding auto-configuration

Use exclude when an auto-configuration does something you do not want and there is no property to switch it off. In Spring Boot 4 the auto-configuration classes moved into per-technology modules, so a Boot 3 import such as org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration no longer compiles; the class is now org.springframework.boot.jdbc.autoconfigure.DataSourceAutoConfiguration. When the class may not be on the classpath, use excludeName or the spring.autoconfigure.exclude property instead, so the build does not depend on it.

Before excluding anything, try the narrower fix. Defining your own bean of the same type usually makes the auto-configuration back off on its own, and most features have an enabled property. Excluding a whole auto-configuration also removes beans you may still rely on, such as the transaction manager that comes with a data source.

Mistakes to avoid

  • Adding a second @SpringBootApplication class, often in a test folder. Test slices search upwards for one, and two in the same tree cause confusing failures.
  • Adding @ComponentScan or @EnableAutoConfiguration next to it. They are already there, and a separate @ComponentScan replaces Boot's default filters.
  • Using scanBasePackages to paper over a misplaced main class. Move the class instead.

Example

Example · java
import java.time.Clock;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;

@SpringBootApplication
public class OrdersApplication {

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

    // The main class is a @Configuration, so small app-wide beans can live here.
    @Bean
    Clock clock() {
        return Clock.systemUTC();
    }
}

// Found by component scanning because it sits in the same package (or below).
@Service
class OrderNumberService {

    private final Clock clock;

    OrderNumberService(Clock clock) {
        this.clock = clock;
    }

    String next() {
        return "ORD-" + clock.millis();
    }
}

When to use it

  • Bootstrapping a REST API so its controllers, services and repositories under the root package are registered automatically
  • Keeping a reporting service from creating a DataSource even though a JDBC driver is on the classpath
  • Pulling components from a shared internal package into an application whose main class lives elsewhere

Frequently asked questions

Why is my controller not found even though it has @RestController?

It is almost always outside the main class's package tree. Scanning starts at the package of the @SpringBootApplication class and only goes down. Move the main class to the root package, or the controller under it.

Where is DataSourceAutoConfiguration in Spring Boot 4?

Spring Boot 4 split auto-configuration into modules, so it is org.springframework.boot.jdbc.autoconfigure.DataSourceAutoConfiguration. Use excludeName or spring.autoconfigure.exclude if you would rather not import it.

Can I have two @SpringBootApplication classes in one project?

Avoid it. Tests search upwards from their package for a single @SpringBootConfiguration, and a second one in the tree changes which configuration they load, or fails when two are found at the same level.

More examples

Excluding one auto-configuration by class

The Spring Boot 4 package is org.springframework.boot.jdbc.autoconfigure. Excluding the data source also means no DataSource bean exists, so anything that needs one (JdbcClient, Flyway, JPA) will not be configured either.

Example · java
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.jdbc.autoconfigure.DataSourceAutoConfiguration;

// A service that has a JDBC driver on the classpath for a tool,
// but must not create a DataSource of its own.
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class ReportingApplication {

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

Excluding through configuration instead

spring.autoconfigure.exclude takes a comma-separated list of class names. Setting debug=true prints the conditions evaluation report at startup, which is the quickest way to see what was applied and what backed off.

Example · properties
# Same effect as exclude = ..., but no compile-time dependency on the class,
# and it can differ per profile or environment.
spring.autoconfigure.exclude=org.springframework.boot.jdbc.autoconfigure.DataSourceAutoConfiguration

# Print which auto-configurations matched and why (startup report).
debug=true

Scanning a shared package as well

Once scanBasePackages is set, the default (the main class's own package) is replaced, so the application's own root must be listed too. For a library you own, an auto-configuration of its own is usually cleaner than widening the scan.

Example · java
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

// The main class lives in com.example.orders, but a shared library
// of components lives in com.example.common. List both roots.
@SpringBootApplication(scanBasePackages = {"com.example.orders", "com.example.common"})
public class OrdersApplication {

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

Discussion

  • Be the first to comment on this lesson.