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.