1. Overview

The Spring framework lets us configure the application context in different ways which include XML-based, Java-based and annotation-based approaches.

In this tutorial, we're going to look at Spring's annotation-based configuration. In the end, we'll have a sample application configured through the usage of Spring annotations.

2. @Component Annotation

Firstly, let's look at how we can define a bean.

For this purpose, Spring provides the @Component annotation which marks a class as a bean. Although there are other stereotype annotations like @Service and @Controller, the @Component annotation is the most fundamental one. During the application startup, Spring parses the @Component annotated classes and creates bean definitions:

@Component
public class ChatRoomService {

    public void start(){
        System.out.println("Starting chat room");
    }
}

Here, we have ChatRoomService class and we're annotating it with @Component. After the application startup, an instance of ChatRoomService will live as a bean in the ApplicationContext.

The @Component annotation also lets us define a bean name:

@Component("history")
public class HistoryService {

    public void store(){
        System.out.println("Storing the history");
    }
}

Here, we're annotating the HistoryService class with @Component. Moreover, we're defining the bean's name as history.

3. @Autowired Annotation

Now, let's look at how we can wire beans.

In the previous examples, we've just created beans living in isolation. In order to compose a bean with another bean, Spring provides the @Autowired annotation. The main purpose of this annotation is to wire a bean into another bean as a dependency:

@Component
public class ChatService {

    private final HistoryService historyService;

    private final ChatRoomService chatRoomService;

    @Autowired
    public ChatService(HistoryService historyService, ChatRoomService chatRoomService) {
        this.historyService = historyService;
        this.chatRoomService = chatRoomService;
    }

    // Other methods
}

Here, we're creating another bean - ChatService. Additionally, we're specifying previously created beans as instance members of ChatService. In order for Spring to inject these beans, we're annotating the constructor with @Autowired. As a result, Spring will look for HistoryService and ChatRoomService beans in the application context and then will pass them to the constructor.

4. @ComponentScan Annotation

Finally, let's look at how we can control component scanning.

Spring should scan our application to find the @Component annotated classes. Moreover, it should also search for @Autowired usages to auto-wire beans. For this purpose, Spring gives us the @ComponentScan annotation. Through the usage of @ComponentScan, we can tell Spring under which packages it should look for components. Although specifying package names is the most common approach, the @Component annotation provides other means to fine-tune the scanning process:

@ComponentScan
public class Application {

    public static void main(String[] args) {
        ConfigurableApplicationContext applicationContext = new AnnotationConfigApplicationContext(Application.class);

        ChatService chatService = applicationContext.getBean(ChatService.class);
        chatService.chat();

        applicationContext.close();
    }
}

Here, we have the Application class which is annotated with the @ComponentScan annotationNote that in our case @ComponentScan doesn't have any package specification. This is because when the package name is not specified, Spring starts looking for components from the current package. As an example, @ComponentScan("com.javabyexamples.spring.core.annotationconfig") produces the same result.

5. Overview

In this tutorial, we've looked at annotation-base configuration of Spring. We've also seen the usages of @Component, @Autowired and @ComponentScan annotations.

Check out the source code over on Github.