Component scanning is how Spring automatically discovers classes annotated with @Component (and its specializations) and registers them as beans, with no XML or manual @Bean needed. @SpringBootApplication includes @ComponentScan, which scans the package of the main class and all its sub-packages. It is used so you can just annotate a class and have it become a managed bean, which keeps configuration small and the code organized by package. Classes outside the scanned packages are invisible to Spring unless you widen the scan.
Types
- Default scan:
@SpringBootApplicationscans the main class’s package and its sub-packages. - Custom scan:
@ComponentScan(basePackages = "...")or@SpringBootApplication(scanBasePackages = {...})adds other packages. - Type-safe scan:
@ComponentScan(basePackageClasses = SomeClass.class)scans the package of a marker class. - Filtered scan:
includeFiltersandexcludeFilterspick or skip classes by annotation, type, or regex. - Detected annotations:
@Component,@Service,@Repository,@Controller/@RestController,@Configuration.
Hands-on Experiment: Creating a spring boot application along with Component Scanning
The following steps are involved in developing this hands-on experiment.
Step 1: Generate the Project
Step 2: Project Structure
Step 3: pom.xml
Step 4: application.yml
Step 5: Create Entity Class
Step 6: Create Repository Interface
Step 7: Create Service Class
Step 8: Create Controller Class
Step 9: Main Application Class
Step 10: Run the Main Application Class
Step 1: Configure the Project on Spring Initializr
Go to start.spring.io and set:
- Project: Maven
- Language: Java
- Spring Boot version: 3.2.x
- Group: com.example
- Artifact: studentscan
- Name: studentscan
- Package name: com.example.studentscan
- Packaging: Jar
- Java: 17
- Dependencies: Spring Web, Spring Data JPA, MySQL Driver
Click Generate to download the ZIP, then extract and import it into your IDE as a Maven project.
Step 2: Generated Project Structure

Step 3: Explore pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>student-scan-simple</artifactId>
<version>1.0.0</version>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Step 4: application.yml
spring:
datasource:
url: jdbc:mysql://localhost:3306/student_scan_simple_db?createDatabaseIfNotExist=true&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
username: root
password: password
jpa:
hibernate:
ddl-auto: update
show-sql: true
server:
port: 8082Code language: JavaScript (javascript)
Step 5: Create Entity class
package com.example.studentscan.entity;
import jakarta.persistence.*;
@Entity
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String course;
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getCourse() { return course; }
public void setCourse(String course) { this.course = course; }
}
Step 6: Create Repository interface
package com.example.studentscan.repository;
import com.example.studentscan.entity.Student;
import org.springframework.data.jpa.repository.JpaRepository;
public interface StudentRepository extends JpaRepository<Student, Long> {
}
Step 7: Create Service class
package com.example.studentscan.service;
import com.example.studentscan.entity.Student;
import com.example.studentscan.repository.StudentRepository;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class StudentService {
private final StudentRepository repository;
public StudentService(StudentRepository repository) {
this.repository = repository;
}
public Student save(Student student) {
return repository.save(student);
}
public List<Student> findAll() {
return repository.findAll();
}
public Student findById(Long id) {
return repository.findById(id).orElseThrow(() -> new RuntimeException("Student not found: " + id));
}
}
Step 8: Create Controller class
package com.example.studentscan.controller;
import com.example.studentscan.entity.Student;
import com.example.studentscan.service.StudentService;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api/students")
public class StudentController {
private final StudentService service;
public StudentController(StudentService service) {
this.service = service;
}
@PostMapping
public Student create(@RequestBody Student student) {
return service.save(student);
}
@GetMapping
public List<Student> getAll() {
return service.findAll();
}
@GetMapping("/{id}")
public Student getById(@PathVariable Long id) {
return service.findById(id);
}
}
package com.example.studentscan.config;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.util.ClassUtils;
import java.util.Arrays;
// A @Component too - found by scanning. Prints every scanned bean at startup.
@Component
public class ScanPrinter implements CommandLineRunner {
private final ApplicationContext context;
public ScanPrinter(ApplicationContext context) {
this.context = context;
}
@Override
public void run(String... args) {
System.out.println("===== Beans found by component scanning =====");
Arrays.stream(context.getBeanDefinitionNames())
.filter(n -> context.getType(n) != null
&& ClassUtils.getUserClass(context.getType(n)).getName().startsWith("com.example"))
.sorted()
.forEach(n -> System.out.println(" -> " + n + " (" + ClassUtils.getUserClass(context.getType(n)).getPackageName() + ")"));
System.out.println("=============================================");
}
}
Step 9: Main Application
package com.example.studentscan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
// Scans com.example.studentscan and all sub-packages (controller, service, repository, config)
@SpringBootApplication
public class StudentScanApplication {
public static void main(String[] args) {
SpringApplication.run(StudentScanApplication.class, args);
}
}
Step 10: Run the StudentScanApplication

