Spring Top

I just announced the new Learn Spring course, focused on the fundamentals of Spring 5 and Spring Boot 2:

>> CHECK OUT THE COURSE

1. Overview

In this tutorial, we're going to learn about the differences between two major XML configuration elements of Spring: <context:annotation-config> and <context:component-scan>.

2. Bean Definitions

As we all know, Spring provides us with two ways to define our beans and dependencies: XML configuration and Java annotations. We can also categorize Spring's annotations under two groups: dependency injection annotations and bean annotations.

Prior to annotations, we had to manually define all our beans and dependencies in XML configuration files. Now thanks to Spring's annotations, it can automatically discover and wire all our beans and dependencies for us. So, we can at least eliminate the XML needed for beans and dependencies.

However, we should remember that annotations are useless unless we activate them. In order to activate them, we can add either <context:annotation-config> or <context:component-scan> on top of our XML file.

In this section, we'll see how <context:annotation-config> and <context:component-scan> differ from each other in terms of their ways of activating annotations.

3. Annotation Activation by <context:annotation-config>

The <context:annotation-config> annotation is mainly used to activate the dependency injection annotations. @Autowired, @Qualifier@PostConstruct, @PreDestroy, and @Resource are some of the ones that <context:annotation-config> can resolve.

Let's make a simple example to see how <context:annotation-config> can simplify the XML configuration for us.

First, let's create a class with a dependency field:

public class UserService {
    @Autowired
    private AccountService accountService;
}
public class AccountService {}

Now, let's define our beans.

<bean id="accountService" class="AccountService"></bean>

<bean id="userService" class="UserService"></bean>

Before going further let's point out that we still need to declare beans in the XML. That is because <context:annotation-config> activates the annotations only for the beans already registered in the application context.

As can be seen here, we annotated the accountService field using @Autowired. @Autowired tells Spring that this field is a dependency that needs to be automatically wired by a matching bean.

If we didn't use @Autowired, then we would need to set the accountService dependency manually:

<bean id="userService" class="UserService">
    <property name="accountService" ref="accountService"></property>
</bean>

Now, we can refer to our beans and dependencies in a unit test:

@Test
public void givenContextAnnotationConfig_whenDependenciesAnnotated_thenNoXMLNeeded() {
    ApplicationContext context
      = new ClassPathXmlApplicationContext("classpath:annotationconfigvscomponentscan-beans.xml");

    UserService userService = context.getBean(UserService.class);
    AccountService accountService = context.getBean(AccountService.class);

    Assert.assertNotNull(userService);
    Assert.assertNotNull(accountService);
    Assert.assertNotNull(userService.getAccountService());
}

Hmm, something is wrong here. It looks like Spring isn't wiring the accountService even though we annotated it by @Autowired. It looks like @Autowired is not active. In order to solve this issue, we'll simply add the following line on top of our XML file:

<context:annotation-config/>

4. Annotation Activation by <context:component-scan>

As similar to <context:annotation-config>, <context:component-scan> can recognize and process the dependency injection annotations too. Moreover, <context:component-scan> recognizes bean annotations that <context:annotation-config> doesn't detect.

Basically, <context:component-scan> detects the annotations by package scanning. To put it differently, it tells Spring which packages need to be scanned to look for the annotated beans or components.

@Component@Repository, @Service, @Controller, @RestController, and @Configuration are several ones that <context:component-scan> can detect.

Now let's see how we can simplify our previous example:

@Component
public class UserService {
    @Autowired
    private AccountService accountService;
}

@Component
public class AccountService {}

Here, the @Component annotation marks our classes as beans. Now, we can clean out all the bean definitions from our XML file. And of course, we need to keep the <context:component-scan> on top of it:

<context:component-scan
  base-package="com.baeldung.annotationconfigvscomponentscan.components" />

Finally, let's note that Spring will look for the annotated beans and dependencies under the package indicated by the base-package attribute.

5. Conclusion

In this tutorial, we looked through the differences between <context:annotation-config> and <context:component-scan>.

Code samples, as always, are over on GitHub.

Spring bottom

I just announced the new Learn Spring course, focused on the fundamentals of Spring 5 and Spring Boot 2:

>> CHECK OUT THE COURSE
Comments are closed on this article!