context:component- scan

context:component- scan element helps to identify the java classes which can be registered as a spring beans.

Let us understand how context:component- scan works ?

step 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

Create Person.java

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");
	}

}


Create 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 {

}


Create 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.

The above beans.xml 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>


Create MainClient.java

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

1) 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.

2) 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 sub-packages of componentscan-filters even though they are not annotated.

LoginDAO.java

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.java

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>


MainClient.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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

Package Hierarchy is given below

component-scan-filter-image1

LoginDAO.java

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.java

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>


MainClient.java

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  {
    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

beans.xml

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 MainClient.java

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