Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Spring Framework provides component scanning; Spring Boot makes it convenient to use through @SpringBootApplication. That annotation combines Boot configuration, auto-configuration, and component scanning. Unless you configure a different scan root, scanning starts in the package of the class bearing the annotation and continues into its subpackages. That package boundary is the key to understanding which beans Spring finds—and why a bean may be missing or a test slice may unexpectedly load extra configuration.

Spring Framework and Spring Boot have different roles

Spring Framework supplies the application context and the machinery that discovers components and registers them as bean definitions. Spring Boot builds conventions and auto-configuration around that framework; it does not replace the framework’s scanner.

In a Boot application, the usual entry point is @SpringBootApplication. Boot documents that it enables three features: @SpringBootConfiguration, @EnableAutoConfiguration, and @ComponentScan. The first marks the application’s configuration, the second enables Boot’s auto-configuration, and the third discovers application components.

What Spring component scanning finds

With the default filters enabled, component scanning looks for Spring stereotype annotations, including:

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • @Component
  • @Service
  • @Repository
  • @Controller
  • @Configuration

Custom annotations can also mark candidates when they are themselves meta-annotated with @Component. Finding a candidate means the scanner registers a bean definition; it is not a search for every Java class on the classpath.

Where the default scan starts

If @ComponentScan has no explicit package, scanning begins in the package of the class that declares it and proceeds recursively through subpackages. In a conventional Boot application, put the main application class in a root package above the application’s controllers, services, repositories, and configuration:

package com.example.myapp;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

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

With this layout, classes in packages such as com.example.myapp.service and com.example.myapp.web are within the default scan. A class in a sibling package such as com.example.shared is outside it. Boot recommends a root package that keeps component scanning focused on the project: a root that is too broad can make scanning read classes from unrelated JARs, while one that is too narrow can omit application beans.

How to scan another package

When a required component is outside the default package tree, set an explicit scan root. Spring’s @ComponentScan supports package names through basePackages (or its value alias), and a type-safe alternative through basePackageClasses. @SpringBootApplication exposes corresponding aliases, scanBasePackages and scanBasePackageClasses.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
@SpringBootApplication(scanBasePackages = {
    "com.example.myapp",
    "com.example.shared"
})
public class MyApplication {
    // ...
}

For a refactor-resistant package marker, define a class or interface in the package you want included, then use its class literal:

@SpringBootApplication(scanBasePackageClasses = {
    MyApplication.class,
    SharedPackageMarker.class
})
public class MyApplication {
    // ...
}

These values define component-scan roots. Keep them as narrow as the application’s actual module boundaries allow: widening discovery can pull in unintended configuration or create duplicate bean names.

For more control, @ComponentScan provides includeFilters and excludeFilters to add or remove candidates. Its useDefaultFilters setting controls whether the standard stereotype filters are active. These options are useful when package boundaries alone do not express which classes should be registered.

Why a bean may not be found

A “bean not found” startup failure commonly means the bean’s class is not in the scan tree, or it is not a candidate under the active filters. Check the package of the class carrying @SpringBootApplication or @ComponentScan, then compare it with the package of the missing bean.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  1. Confirm that the class is annotated with a recognized stereotype, or with a custom annotation meta-annotated by @Component.
  2. Check whether its package is the scan package itself or one of its subpackages.
  3. If it is outside that tree, add a suitably narrow package with scanBasePackages or scanBasePackageClasses.
  4. If you use filters, verify that the candidate is included and that default filters have not been disabled unintentionally.
  5. If the scan root is becoming broad or hard to reason about, consider importing the needed configuration explicitly instead.

Broadening the scan is not always the right fix: it can also discover configuration you did not intend to load. Prefer a deliberate package boundary over scanning an unnecessarily large root.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

When to use explicit imports instead of scanning

Scanning trades explicit setup for convenient discovery. Explicit imports make the configuration boundary visible, but require you to name the configuration you want. Boot documents that the features composed by @SpringBootApplication are not mandatory: an application can retain @SpringBootConfiguration and @EnableAutoConfiguration, then use @Import for selected configuration classes instead of component scanning. In that arrangement, component and configuration-properties classes are not detected automatically.

Choice What it offers Trade-off
Component scanning Discovers eligible classes under configured package roots with less per-class configuration. Package boundaries and filters determine what is discovered; broad roots can load unintended configuration.
Explicit @Import Makes selected configuration classes explicit and can provide a more deterministic module boundary. Requires naming the configuration to load; component and configuration-properties classes are not discovered automatically in this arrangement.

Use scanning when the package structure is a clear boundary for application components. Prefer explicit imports when you want configuration to be selected deliberately rather than inferred from a scan tree.

Why adding @ComponentScan can break a test slice

Spring Boot’s test-slice setup uses a default scan directive to keep tests such as @DataJpaTest focused. Adding an explicit @ComponentScan to the test application class can override that directive, causing the test to discover application components and user configuration that the slice would otherwise leave out.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

When a slice test starts loading unexpected beans, inspect the test application class for an extra scan declaration. Move the custom directive to a separate configuration class, or provide an explicit test source, so the test can use the configuration it needs without unintentionally widening the slice’s scan.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.