context:component- scan

This element helps to identify the java classes which can be registered as a spring beans.
How it works ?
STPE 1)
All the java classes that need to register as a spring bean must be annotated with at least one of the below annotation
a)@Component
b)@Controller
c)@Repository
d)@Service
e)Any custom annotation that itself has annotated with one of the above annotation

Step 2)
context:component- scan element must have the base-package attribute whose value should be the package name where all the java classes which have any one of the above 5 annotation are defined.

So if we want to make the java class as a spring bean then these 2 steps should be followed
Step 1
Annotate your class with any one of the above annotation
Step 2
Add the package where your java class is available into base-package value.

Lets see the Example below

1
2
3
4
5
6
7
8
9
10
11
package com.kb.componentscan;
 
import org.springframework.stereotype.Component;
 
@Component
public class Person {
    public Person() {
    System.out.println("person");
    }
 
}
package com.kb.componentscan;

import org.springframework.stereotype.Component;

@Component
public class Person {
	public Person() {
	System.out.println("person");
	}

}

Car.java

1
2
3
4
5
6
7
8
package com.kb.componentscan;
 
import org.springframework.stereotype.Component;
 
@Component
public class Car {
 
}
package com.kb.componentscan;

import org.springframework.stereotype.Component;

@Component
public class Car {

}

beans.xml

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:component-scan base-package="com.kb.componentscan" />
</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" />
</beans>

Look at both the classes are annotated with @Component
and both the classes are in the same package com.kb.componentscan and this package is included inside context:component-scan.

So now both the classes are considered as spring beans.
It is same as below

1
2
3
4
5
6
7
8
9
10
11
12
<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.Person"/>
     
<bean id="car" class= "com.kb.componentscan.Car"/>
</beans>
<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.Person"/>
     
<bean id="car" class= "com.kb.componentscan.Car"/>
</beans>

Client program

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.kb.componentscan;
 
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/beans.xml");
    Person person= (Person)applicationContext.getBean("person");
        System.out.println("end");
    }
 
    
}
package com.kb.componentscan;

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/beans.xml");
	Person person= (Person)applicationContext.getBean("person");
		System.out.println("end");
	}

	
}

Output

Context:component-scan – filtering
Assume inside a package com.kb, we have 2 sub packages service and DAO
I want all classes comes under both the package service and DAO to register as a spring bean,even though they are not annotated with any of the stereotype annotation then I cannot achieve it with just context:component-scan
but if we use filtering we can achieve it easily
Filter types are
1)context:include-filter – it suggests context:component-scan what needs to be registered as a spring bean.
2)context:exclude-filter – it suggest context:component-scan what not to be registered as a spring bean.

Context:include-filter and Context:exclude-filter have 2 attributes
a)type -> Spring supports 5 types of Filter expression and they are
annotation: specify an annotation type for filtering.
assignable: specify a class/interface for filtering.
aspectj: specify an AspectJ pointcut expression for matching the classes.
regex: specify a regular expression for matching the classes.
custom: A custom implementation of the org.springframework.core.type.TypeFilter interface.
b)expression – specifies the expression to consider and evaluate based on filter type.

Let’s see with the regex example as below
Package Hierarchy is given below
component-scan-filter-image1
Now I want to register those classes which comes under subpackages of componentscan-filters even though they are not annotated.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.kb.componentscan_filters.DAO;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
 
import com.kb.componentscan_filters.service.LoginService;
 
public class LoginDAO {
@Autowired
LoginService loginService;
 
public void hello(){
    System.out.println("hello");
}
}
package com.kb.componentscan_filters.DAO;

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

import com.kb.componentscan_filters.service.LoginService;

public class LoginDAO {
@Autowired
LoginService loginService;

public void hello(){
	System.out.println("hello");
}
}

LoginService

1
2
3
4
5
package com.kb.componentscan_filters.service;
 
public class LoginService {
 
}
package com.kb.componentscan_filters.service;

public class LoginService {

}

beans.xml

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">
 
<context:component-scan base-package="com.kb.componentscan_filters">
    <context:include-filter type="regex" expression="com.kb.componetscan_filters.service.*"/>
    <context:include-filter type="regex" expression="com.kb.componetscan_filters.DAO.*"/>
</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_filters">
    <context:include-filter type="regex" expression="com.kb.componetscan_filters.service.*"/>
    <context:include-filter type="regex" expression="com.kb.componetscan_filters.DAO.*"/>
</beans>

Client program

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.kb.componentscan_filters;
 
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
import com.kb.componentscan_filters.DAO.LoginDAO;
 
public class MainClient  {
        public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("com/kb/componentscan_filters/beans.xml");
        LoginDAO loginDAO = (LoginDAO)applicationContext.getBean("loginDAO");
        loginDAO.hello();
        System.out.println("end");
    }
 
    
 
}
package com.kb.componentscan_filters;

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

import com.kb.componentscan_filters.DAO.LoginDAO;

public class MainClient  {
		public static void main(String[] args) {
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("com/kb/componentscan_filters/beans.xml");
		LoginDAO loginDAO = (LoginDAO)applicationContext.getBean("loginDAO");
		loginDAO.hello();
		System.out.println("end");
	}

	

}

Output

Include vs Exclude Filter priority

Lets define the situation like this

Package Hierarchy is given below

component-scan-filter-image1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.kb.componentscan_filters.DAO;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
 
import com.kb.componentscan_filters.service.LoginService;
 
public class LoginDAO {
@Autowired
LoginService loginService;
 
public void hello(){
    System.out.println("hello");
}
}
package com.kb.componentscan_filters.DAO;

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

import com.kb.componentscan_filters.service.LoginService;

public class LoginDAO {
@Autowired
LoginService loginService;

public void hello(){
	System.out.println("hello");
}
}

LoginService

1
2
3
4
5
package com.kb.componentscan_filters.service;
 
public class LoginService {
 
}
package com.kb.componentscan_filters.service;

public class LoginService {

}

beans.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?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_filters">
<context:exclude-filter type="regex" expression=".*service.*"/>
 
<context:exclude-filter type="regex" expression=".*DAO.*"/>
    
<context:include-filter type="regex" expression.*service.*"/>
 
<context:include-filter type="regex" expression=".*DAO.*"/>
</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_filters">
<context:exclude-filter type="regex" expression=".*service.*"/>

<context:exclude-filter type="regex" expression=".*DAO.*"/>
    
<context:include-filter type="regex" expression.*service.*"/>

<context:include-filter type="regex" expression=".*DAO.*"/>
</beans>

Client program

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.kb.componentscan_filters;
 
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
import com.kb.componentscan_filters.DAO.LoginDAO;
 
public class MainClient  {
    static ApplicationContext applicationContext ;
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("com/kb/componentscan_filters/beans.xml");
        LoginDAO loginDAO = (LoginDAO)applicationContext.getBean("loginDAO");
        loginDAO.hello();
        System.out.println("end");
    }
 
    
 
}
package com.kb.componentscan_filters;

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

import com.kb.componentscan_filters.DAO.LoginDAO;

public class MainClient  {
	static ApplicationContext applicationContext ;
	public static void main(String[] args) {
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("com/kb/componentscan_filters/beans.xml");
		LoginDAO loginDAO = (LoginDAO)applicationContext.getBean("loginDAO");
		loginDAO.hello();
		System.out.println("end");
	}

	

}

Output


It means first filter inside xml must be include always.
If we put exclude first then we will end up with the above exception.

Now Reverse the order – place include first and then exclude

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?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_filters">  
 
<context:include-filter type="regex" expression.*service.*"/>
<context:include-filter type="regex" expression=".*DAO.*"/>
 
<context:exclude-filter type="regex" expression=".*service.*"/>
 
<context:exclude-filter type="regex" expression=".*DAO.*"/>
 
</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_filters">  
 
<context:include-filter type="regex" expression.*service.*"/>
<context:include-filter type="regex" expression=".*DAO.*"/>

<context:exclude-filter type="regex" expression=".*service.*"/>

<context:exclude-filter type="regex" expression=".*DAO.*"/>

</beans>

Run above client program
Output

This is because include filter is trying to take the beans registration but exclude filter overrides the same and exclude those beans from the registration.
Hence no bean is registered and hence the exception above is appearing.

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