LearnAI ToolsCareerPractice BuildsPlayContact
Lesson 1416 min read

Component Scanning

Let Spring find and register your beans automatically with @ComponentScan and the @Component family of annotations.

Introduction

Writing a @Bean method for every single class in a medium-sized application quickly becomes tedious. Component scanning solves that problem: you mark classes with an annotation, tell Spring which package to look in, and the container finds and registers them on its own.

What You Will Learn
  • How Spring discovers classes on the classpath
  • How to mark a class as a component
  • How to enable and configure scanning with @ComponentScan
  • How to include or exclude specific classes from a scan

How Component Scanning Works

At startup, Spring scans the packages you specify, looking for classes annotated with @Component (or one of the specialized annotations built on top of it, such as @Service or @Repository). For each match, it registers a bean definition automatically, using a camel-cased version of the class name as the default bean name.

Marking a Class with @Component

Any plain class can become a Spring-managed bean simply by adding @Component above the class declaration.

GreetingService.java
package com.example.app.service;
import org.springframework.stereotype.Component;
@Component
public class GreetingService {
public String greet(String name) {
return "Hello, " + name + "!";
}
}

Enabling the Scan

Component scanning does not run by itself; a configuration class has to opt in with @ComponentScan and tell Spring which base package to search.

AppConfig.java
package com.example.app;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = "com.example.app")
public class AppConfig {
}
Main.java
ApplicationContext context =
new AnnotationConfigApplicationContext(AppConfig.class);
GreetingService greetingService = context.getBean(GreetingService.class);
System.out.println(greetingService.greet("PrograMinds"));
Console Output

Click Run to see what this code prints.

Good to Know

If you omit basePackages, @ComponentScan defaults to scanning the package that the configuration class itself lives in, plus every sub-package underneath it. This is why placing your main configuration class at the root package of your project is a common convention.

Controlling What Gets Scanned

You can narrow or widen what gets picked up using filters, which is useful for excluding test doubles or legacy classes from a production scan.

AppConfig.java
@Configuration
@ComponentScan(
basePackages = "com.example.app",
excludeFilters = @ComponentScan.Filter(
type = FilterType.REGEX,
pattern = "com\\.example\\.app\\.legacy\\..*"
)
)
public class AppConfig {
}
AttributePurpose
basePackagesWhich package(s) to scan, including sub-packages
basePackageClassesType-safe alternative: scan the packages containing these classes
includeFiltersNarrow scanning to classes matching extra criteria
excludeFiltersSkip classes that would otherwise be picked up

Common Mistakes

Avoid These Mistakes
  • Placing @Component classes in a package that is outside the scanned base package, so they are silently never registered.
  • Adding @ComponentScan without specifying a base package on a configuration class that lives in an unrelated package, missing the intended classes entirely.
  • Defining the same bean twice: once via component scanning and again via an explicit @Bean method, causing a naming conflict.
  • Forgetting that abstract classes and interfaces cannot be scanned as components; only concrete classes can.

Best Practices

  • Put your main configuration or application class at the root package so the default scan naturally covers everything underneath it.
  • Keep component scanning to your own application code; use @Bean methods for third-party or externally defined classes.
  • Use basePackageClasses instead of string-based basePackages when you want refactor-safe, compile-checked scan targets.
  • Reserve exclude filters for genuinely special cases rather than routinely hiding classes from the scan.

Frequently Asked Questions

The class name with its first letter lowercased, so GreetingService becomes greetingService. You can override it by passing a value to @Component, e.g. @Component("myGreetingService").

Usually not. @SpringBootApplication already includes @ComponentScan, scanning the package the main class lives in and everything below it.

Yes, as long as those classes are on the classpath and their package matches (or is nested inside) the scanned base package.

Key Takeaways

  • @Component marks a class as eligible for automatic discovery.
  • @ComponentScan tells Spring which packages to search for annotated classes.
  • Without a specified basePackages, scanning defaults to the configuration class's own package and its sub-packages.
  • Filters let you fine-tune exactly which classes are included or excluded.
  • Spring Boot enables component scanning automatically through @SpringBootApplication.

Summary

Component scanning removes the busywork of registering every class by hand, letting the container discover your beans as long as they are annotated and sit inside a scanned package. Not every @Component is the same, though — some carry extra meaning about the role a class plays in your application. That is exactly what stereotype annotations cover next.

Next Lesson →

Stereotype Annotations