How Spring Boot @Component and @ComponentScan annotations work
The job of the Spring IoC container is to keep your business logic clean by managing the lifecycle and configuration of objects that would otherwise make things messy.
But the Spring container doesn't automatically know which beans to manage. As a Spring developer, it's your job to make it explicitly clear which beans Spring should take care of and how. That's where Spring's @Component and @ComponentScan annotations come in.
What does Spring's @Component annotation do?
If you create a JavaBean that you intend to be managed by Spring, one way to get the IoC container's attention is to decorate that class with Spring's @Component annotation.
The following code shows two classes are best managed by the Spring container, so both are decorated with the @Component annotation. However, simply adding a @Component annotation to a JavaBean doesn't mean it will be automatically managed by the Spring framework. The annotation only causes Spring to manage the decorated class if the container is explicitly told to search for @Component annotated classes. That's where the @ComponentScan annotation comes in.
@Component
class Score {
int wins, losses, ties;
}
@Component
class Game {
@Autowired
Score score;
public void playTheGame(String gesture) {
score.wins++;
}
}
What does Spring's @ComponentScan annotation do?
If, during initialization, the Spring container loads a bean decorated with the @ComponentScan annotation, Spring will search within that class' package and subpackages for @Component annotated classes. If it finds any, the Spring IoC container will automatically manage them.
In the following code, we see the SimpleExample class both decorated with the @ComponentScan annotation and loaded into Spring's ApplicationContext when the Spring IoC container is initialized. The ApplicationContext is the name of the Java interface that represents the Spring IoC container.
@ComponentScan
public class SimpleExample {
public static void main(String[] args) {
var springApp = new SpringApplication(Score.class, Game.class);
var springContainer = springApp.run(args);
var game = springContainer.getBean(Game.class);
game.playTheGame("rock");
System.out.print(game.score.wins);
System.out.print(game.score.wins); // prints 1
}
}
When this code runs, both the Game class and the Score class are managed by the Spring container.
When the main method runs, an instance of the Game class is pulled from the container, and the Game's score is initialized through Spring's dependency injection mechanism. When the number of wins is printed to the console, the correct output of 1 is displayed.
Spring's @Component and @ComponentScan together
As you can see, the @ComponentScan and @Component annotations work together.
The @Component annotation indicates that a class should be managed by the Spring IoC container if discovered during a component scan, and a class decorated with the @ComponentScan annotation is what actually triggers the scanning for components.
Cameron McKenzie has been a Java EE software engineer for 20 years. His current specialties include Agile development; DevOps; Spring; and container-based technologies such as Docker, Swarm and Kubernetes.