context:component-scan vs context:annotation-config

context:annotation-config

This tag is used to activate the annotations inside the beans which are already registered with the Application context.

Basically it is used for Autowiring.

Context:component-scan

This tag does what context:annotation-config does and in addition to that it also scans the packages and registers the stereotype annotated classes as a spring beans.

Detailed example to understand the same

Let’s start with 3 classes Person,Car,Address. Person is having has a relationship with Car and Address.

1
2
3
4
5
6
7
8
package com.kb.componentscan_annotationconfig;
 
public class Car {
    public Car() {
        System.out.println("creating the Car bean "+this);
    }
 
}
package com.kb.componentscan_annotationconfig;

public class Car {
	public Car() {
		System.out.println("creating the Car bean "+this);
	}

}

Address.java

1
2
3
4
5
6
7
package com.kb.componentscan_annotationconfig;
 
public class Address {
public Address() {
    System.out.println("creating the Address bean "+this);
}
}
package com.kb.componentscan_annotationconfig;

public class Address {
public Address() {
	System.out.println("creating the Address bean "+this);
}
}

Person.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package com.kb.componentscan_annotationconfig;
 
public class Person {
private Car car;
private Address address;
    
public Person() {
    System.out.println("creating the Person bean "+this);
}
 
public Car getCar() {
    return car;
}
 
public void setCar(Car car) {
    System.out.println("setting car bean with"+car);
    this.car = car;
}
 
public Address getAddress() {
    return address;
}
 
public void setAddress(Address address) {
    System.out.println("setting address  bean with  "+address);
    this.address = address;
}
}
package com.kb.componentscan_annotationconfig;

public class Person {
private Car car;
private Address address;
	
public Person() {
	System.out.println("creating the Person bean "+this);
}

public Car getCar() {
	return car;
}

public void setCar(Car car) {
	System.out.println("setting car bean with"+car);
	this.car = car;
}

public Address getAddress() {
	return address;
}

public void setAddress(Address address) {
	System.out.println("setting address  bean with  "+address);
	this.address = address;
}
}

beans.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="UTF-8"?>
 
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<bean id="person" class="com.kb.componentscan_annotationconfig.Person">
<property name="car" ref="car"/>
<property name="address" ref="address"/>
</bean>
 
<bean id="car" class="com.kb.componentscan_annotationconfig.Car"/>
<bean id="address" class="com.kb.componentscan_annotationconfig.Address"/>
</beans>
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<bean id="person" class="com.kb.componentscan_annotationconfig.Person">
<property name="car" ref="car"/>
<property name="address" ref="address"/>
</bean>

<bean id="car" class="com.kb.componentscan_annotationconfig.Car"/>
<bean id="address" class="com.kb.componentscan_annotationconfig.Address"/>
</beans>

MainClient.java

1
2
3
4
5
6
7
8
9
10
11
12
package com.kb.componentscan_annotationconfig;
 
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
public class MainClient {
    public static void main(String[] args) {
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("com/kb/componentscan_annotationconfig/beans.xml");
    }
}
package com.kb.componentscan_annotationconfig;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainClient {
	public static void main(String[] args) {
	ApplicationContext applicationContext = new ClassPathXmlApplicationContext("com/kb/componentscan_annotationconfig/beans.xml");
	}
}

Run the client to see the output

Output is as expected and dependency injection is achived with XML.

Now lets try to use annotation for DI.

Now class Person becomes as below after autowiring
Person.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package com.kb.componentscan_annotationconfig;
import org.springframework.beans.factory.annotation.Autowired;
 
public class Person {
private Car car;
private Address address;
    
public Person() {
    System.out.println("creating the Person bean "+this);
}
 
public Car getCar() {
    return car;
}
 
@Autowired
public void setCar(Car car) {
    System.out.println("setting car bean with"+car);
    this.car = car;
}
 
public Address getAddress() {
    return address;
}
@Autowired
public void setAddress(Address address) {
    System.out.println("setting address  bean with  "+address);
    this.address = address;
}
}
package com.kb.componentscan_annotationconfig;
import org.springframework.beans.factory.annotation.Autowired;

public class Person {
private Car car;
private Address address;
	
public Person() {
	System.out.println("creating the Person bean "+this);
}

public Car getCar() {
	return car;
}

@Autowired
public void setCar(Car car) {
	System.out.println("setting car bean with"+car);
	this.car = car;
}

public Address getAddress() {
	return address;
}
@Autowired
public void setAddress(Address address) {
	System.out.println("setting address  bean with  "+address);
	this.address = address;
}
}

Now I have used autowiring to inject Car and Address, so remove those lines from xml

1
2
<property name="car" ref="car"/>
<property name="address" ref="address"/>
<property name="car" ref="car"/>
<property name="address" ref="address"/>

And now xml is as below

1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0" encoding="UTF-8"?>
 
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<bean id="person" class="com.kb.componentscan_annotationconfig.Person"/>
<bean id="car" class="com.kb.componentscan_annotationconfig.Car"/>
<bean id="address" class="com.kb.componentscan_annotationconfig.Address"/>
</beans>
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<bean id="person" class="com.kb.componentscan_annotationconfig.Person"/>
<bean id="car" class="com.kb.componentscan_annotationconfig.Car"/>
<bean id="address" class="com.kb.componentscan_annotationconfig.Address"/>
</beans>

Now run our client to load application context

Output

Why we didn’t get setter method’s output means, why Car and Address are not injected to Person even though we used @Autowired ?

Yes this is because Annotation are good feature by themselves but they are just annotated they cant do any processing.

We need some processing element which finds those annotations and perform the corresponding action.

Yes that processing element for Autowiring is < context:annotation-config >

This will perform the corresponding action based on the annotation defined inside the registered beans.

Now modify our beans.xml as below

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version="1.0" encoding="UTF-8"?>
 
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<bean id="person" class="com.kb.componentscan_annotationconfig.Person"/>
<bean id="car" class="com.kb.componentscan_annotationconfig.Car"/>
<bean id="address" class="com.kb.componentscan_annotationconfig.Address"/>
<context:annotation-config/>
</beans>
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<bean id="person" class="com.kb.componentscan_annotationconfig.Person"/>
<bean id="car" class="com.kb.componentscan_annotationconfig.Car"/>
<bean id="address" class="com.kb.componentscan_annotationconfig.Address"/>
<context:annotation-config/>
</beans>

We have just added our processing element for autowiring.
We can add it at the beginning or end – does not matter.

Now see the output

It means context:annotation-config reduced bit of xml coding(ie adding bean
references)

Now I am not happy with just 2 lines removal from xml.

So lets remove all the lines from xml and annotate our class with @Component.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package com.kb.componentscan_annotationconfig;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
 
@Component
public class Person {
private Car car;
private Address address;
    
public Person() {
    System.out.println("creating the Person bean "+this);
}
 
public Car getCar() {
    return car;
}
 
@Autowired
public void setCar(Car car) {
    System.out.println("setting car bean with"+car);
    this.car = car;
}
 
public Address getAddress() {
    return address;
}
@Autowired
public void setAddress(Address address) {
    System.out.println("setting address  bean with  "+address);
    this.address = address;
}
}
package com.kb.componentscan_annotationconfig;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class Person {
private Car car;
private Address address;
	
public Person() {
	System.out.println("creating the Person bean "+this);
}

public Car getCar() {
	return car;
}

@Autowired
public void setCar(Car car) {
	System.out.println("setting car bean with"+car);
	this.car = car;
}

public Address getAddress() {
	return address;
}
@Autowired
public void setAddress(Address address) {
	System.out.println("setting address  bean with  "+address);
	this.address = address;
}
}

Car.java

1
2
3
4
5
6
7
8
9
10
package com.kb.componentscan_annotationconfig;
 
import org.springframework.stereotype.Component;
 
@Component
public class Car {
    public Car() {
        System.out.println("creating the Car bean "+this);
    }
}
package com.kb.componentscan_annotationconfig;

import org.springframework.stereotype.Component;

@Component
public class Car {
	public Car() {
		System.out.println("creating the Car bean "+this);
	}
}

Address.java

1
2
3
4
5
6
7
8
9
10
package com.kb.componentscan_annotationconfig;
 
import org.springframework.stereotype.Component;
 
@Component
public class Address {
public Address() {
    System.out.println("creating the Address bean "+this);
}
}
package com.kb.componentscan_annotationconfig;

import org.springframework.stereotype.Component;

@Component
public class Address {
public Address() {
	System.out.println("creating the Address bean "+this);
}
}

Now our beans.xml will have only context:annotation-config element as below

1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0" encoding="UTF-8"?>
 
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:annotation-config/>
</beans>
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:annotation-config/>
</beans>

Run the client and see the output as below

No output – no beans are loaded no autowiring why?

Because works only for the registered ,registered, registered beans.

Yes it never works for the beans which are not registered with spring.

Now replace from beans.xml with as below

1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0" encoding="UTF-8"?>
 
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan base-package="com.kb.componentscan_annotationconfig"></context:component-scan>
</beans>
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan base-package="com.kb.componentscan_annotationconfig"></context:component-scan>
</beans>

Output

scans all the classes inside the specified package and also sub packages inside specified package and register the stereotype annotated classes with the spring context.

Now this has done autodiscovery. And it also does job which is injecting @Autowired beans.

Hence the above output.

Now what if we make our beans.xml as below

1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="UTF-8"?>
 
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd">
    <context:annotation-config/>
<context:component-scan base-package="com.kb.componentscan_annotationconfig"></context:component-scan>
</beans>
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd">
    <context:annotation-config/>
<context:component-scan base-package="com.kb.componentscan_annotationconfig"></context:component-scan>
</beans>

Will the duplicate beans gets registered with the Spring ?

No chance, same above output will come.

This is because both and register with the same processing tool and hence spring intelligently takes only one into consideration.

Which one to consider ?
If I have person who is too strong and one is not that strong – whom we choose ?

Yes Spring is also intelligently choose
Which is more stronger(means does what context:annotation-config does + registering beans) than context:annotation-config.

This is how we can say the difference between and

About the Author

Karibasappa G C (KB)
Founder of javainsimpleway.com
I love Java and open source technologies and very much passionate about software development.
I like to share my knowledge with others especially on technology 🙂
I have given all the examples as simple as possible to understand for the beginners.
All the code posted on my blog is developed,compiled and tested in my development environment.
If you find any mistakes or bugs, Please drop an email to kb.knowledge.sharing@gmail.com

Connect with me on Facebook for more updates

Share this article on