Spring Component Scan Include and Exclude Filter Example

By Arvind Rai, March 13, 2023
This page will walk through Spring component scan include and exclude filter example using JavaConfig and XML configuration. When we use Spring component scan either in JavaConfig or XML configuration, all the classes annotated by @Component, @Service, @Repository and @Controller stereotypes are by default auto detected. Using Spring filter, we can extend the ability of component scan. Using filter, we can include those classes to auto detect which are not annotated by stereotype annotations and at the same time we can exclude those classes not to auto detect which are annotated by stereotype annotations.
Here we will provide complete example of Spring filter to customize component scan.

Component Scan Filter Types

Find the component filter types.
annotation: Component scan of classes can be included and excluded by configuring annotation name applied at class level.

assignable: Using interface name or class name that has been implemented or extended by the classes, we can include and exclude classes in component scanning.

aspect: Using aspect expression targeting classes names, it can be included and excluded in component scanning.

regex: Using regex expression targeting classes names, it can be included and excluded in component scanning.

custom: We can also create custom filter type by implementing org.springframework.core.type.TypeFilter.

Include and Exclude Filter using JavaConfig and XML

Include and exclude filter syntax using JavaConfig is given below.
@ComponentScan(basePackages = "com.concretepage",
     includeFilters = @Filter(type = FilterType.REGEX, pattern="com.concretepage.*.*Util"),
     excludeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = IUserService.class))  
Here FilterType values are FilterType.ANNOTATION, FilterType.ASPECTJ, FilterType.ASSIGNABLE_TYPE, FilterType.REGEX and FilterType.CUSTOM. Include and exclude filter syntax using XML configuration is given below.
<context:component-scan base-package="com.concretepage">
	<context:include-filter type="regex" expression="com.concretepage.*.*Util"/>
        <context:exclude-filter type="assignable" expression="com.concretepage.service.IUserService"/>		        
</context:component-scan>  

Gradle File to Resolve JAR Dependencies

Find the gradle file to resolve JAR dependencies.
build.gradle
dependencies {
    compile 'org.springframework.boot:spring-boot-starter:1.2.7.RELEASE'
    compile 'org.springframework:spring-aspects:4.2.4.RELEASE'    
}   

Filter Type: annotation

For the annotation filter type example, we are creating a utility, service and DAO class. We are also creating a custom annotation. Now we are starting with our custom annotation. This will be a simple annotation for the demo purpose. We will use this annotation at class level.
MyAnnotation.java
package com.concretepage;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyAnnotation {

} 
We are using MyAnnotation custom annotation on our class CalcUtil. This class has not been annotated with Spring @Component, @Service, @Repository or @Controller stereotype annotation, so by default our CalcUtil class will not be auto detected by @ComponentScan. But using Spring include filter, it can be auto-detected. Find the CalcUtil class.
CalcUtil.java
package com.concretepage.util;
import com.concretepage.MyAnnotation;
@MyAnnotation
public class CalcUtil {
	public int addNumbers(int num1, int num2) {
		return num1 + num2;
	}
} 
Now find a DAO which will be annotated with Spring @Repository annotation. By default it will be auto-detected by @ComponentScan. But using Spring exclude filter, we can avoid it to auto detect. Find the BookDAO class.
BookDAO.java
package com.concretepage.dao;
import org.springframework.stereotype.Repository;
@Repository
public class BookDAO {
	public String getWriterByBookId(int bookId) {
		if (bookId == 1) {
			return "Mohan";
		}
		return "Sohan";
	}
} 
Now find a service class which has not been annotated by any annotation. Using Spring include filter, it is possible to auto detect by @ComponentScan. Find the UserService.
UserService.java
package com.concretepage.service;
public class UserService {
	public String getUserRole() {
		return "admin";
	}
} 
Now to filter component scanning, we here using annotation filter type in JavaConfig.
AppConfig.java
package com.concretepage;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Repository;
@Configuration
@ComponentScan(basePackages = "com.concretepage",
     includeFilters = @Filter(MyAnnotation.class),
     excludeFilters = @Filter(Repository.class))
public class AppConfig {

} 
Using above JavaConfig, we will achieve following points within the base package com.concretepage.
1. All classes annotated with @Component, @Service and @Controller will be auto-detected.
2. The classes annotated with @Repository will not be auto-detected.
3. The classes annotated with custom annotation MyAnnotation will be auto-detected.

Now find the Main class to run the application.
SpringFilterAnnotationDemo.java
package com.concretepage;
import org.springframework.beans.BeansException;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.concretepage.dao.BookDAO;
import com.concretepage.service.UserService;
import com.concretepage.util.CalcUtil;
public class SpringFilterAnnotationDemo {
	public static void main(String[] args)  {
	    AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
	    ctx.register(AppConfig.class);
	    ctx.refresh();
	    try {
			CalcUtil calc = ctx.getBean(CalcUtil.class);
			System.out.println("Addition:" +calc.addNumbers(15,30));
	    }catch(BeansException be) {
	    	        System.out.println(be.getMessage());
	    }
	    try {
			BookDAO book = ctx.getBean(BookDAO.class);
			System.out.println("Writer:"+book.getWriterByBookId(1));
	    }catch(BeansException be) {
	    	        System.out.println(be.getMessage());
	    }	    
	    try {
			UserService user = ctx.getBean(UserService.class);
			System.out.println("User Role:"+user.getUserRole());
	    }catch(BeansException be) {
	    	        System.out.println(be.getMessage());
	    }	    
    	    ctx.close();
	}
} 
Find the output.
Addition:45
No qualifying bean of type [com.concretepage.dao.BookDAO] is defined
No qualifying bean of type [com.concretepage.service.UserService] is defined 
Observe the output. Only CalcUtil has been auto-detected.

The equivalent XML configuration of our JavaConfig is given below.
spring-config.xml
<?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.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="com.concretepage">
	 <context:include-filter type="annotation" expression="com.concretepage.MyAnnotation"/>
         <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>		        
    </context:component-scan>	
</beans> 
Find the Main class to run XML configuration example.
SpringFilterXMLDemo.java
package com.concretepage;
import org.springframework.beans.BeansException;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.concretepage.dao.BookDAO;
import com.concretepage.service.UserService;
import com.concretepage.util.CalcUtil;
public class SpringFilterXMLDemo {
	public static void main(String[] args) {
	    AbstractApplicationContext  ctx = new ClassPathXmlApplicationContext("spring-config.xml");
	    try {
			CalcUtil calc = ctx.getBean(CalcUtil.class);
			System.out.println("Addition:" +calc.addNumbers(15,30));
	    }catch(BeansException be) {
	    	        System.out.println(be.getMessage());
	    }
	    try {
			BookDAO book = ctx.getBean(BookDAO.class);
			System.out.println("Writer:"+book.getWriterByBookId(1));
	    }catch(BeansException be) {
	    	        System.out.println(be.getMessage());
	    }	    
	    try {
			UserService user = ctx.getBean(UserService.class);
			System.out.println("User Role:"+user.getUserRole());
	    }catch(BeansException be) {
	    	        System.out.println(be.getMessage());
	    }	    	    
            ctx.close();
    } 
} 
The output here will be same as the output in JavaConfig example.

Filter Type: assignable

To use assignable, we are creating two interfaces.
IUserService.java
package com.concretepage.service;
public interface IUserService {
	String getUserRole();
} 
This interface is being implemented by UserService class.
UserService.java
package com.concretepage.service;
public class UserService implements IUserService {
        @Override
	public String getUserRole() {
		return "admin";
	}
} 
Find another interface.
ICalcUtil.java
package com.concretepage.util;
public interface ICalcUtil {
	int addNumbers(int num1, int num2);
} 
This interface is being implemented by CalcUtil class.
CalcUtil.java
package com.concretepage.util;
public class CalcUtil implements ICalcUtil {
	@Override
	public int addNumbers(int num1, int num2) {
		return num1 + num2;
	}
} 
Now find the JavaConfig where we are using assignable filter.
AppConfig.java
package com.concretepage;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import com.concretepage.service.IUserService;
import com.concretepage.util.ICalcUtil;
@Configuration
@ComponentScan(basePackages = "com.concretepage",
     includeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = IUserService.class),
     excludeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = ICalcUtil.class))
public class AppConfig {
} 
Using above JavaConfig, the classes from the base package com.concretepage are scanned as follows.
1. All classes annotated with @Component, @Service, @Repository and @Controller will be auto-detected.
2. The classes implementing IUserService will be auto-detected.
3. The classes implementing ICalcUtil will not be auto-detected.

When we run SpringFilterAnnotationDemo, we will get the output as follows.
No qualifying bean of type [com.concretepage.util.CalcUtil] is defined
Writer:Mohan
User Role:admin 
Find the XML configuration equivalent to JavaConfig.
spring-config.xml
<context:component-scan base-package="com.concretepage">
	<context:include-filter type="assignable" expression="com.concretepage.service.IUserService"/>
        <context:exclude-filter type="assignable" expression="com.concretepage.util.ICalcUtil"/>		        
</context:component-scan> 
To test the output, run the class SpringFilterXMLDemo and the output will be same as by using JavaConfig.

Filter Type: aspectj

To use aspectj filter type, find the JavaConfig.
AppConfig.java
package com.concretepage;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
@Configuration
@ComponentScan(basePackages = "com.concretepage",
     includeFilters = @Filter(type = FilterType.ASPECTJ, pattern="com.concretepage..*Util+"),
     excludeFilters = @Filter(type = FilterType.ASPECTJ, pattern="com.concretepage..*DAO+"))
public class AppConfig {

} 
The above JavaConfig will provide component scan filter within base package com.concretepage as follows.
1. All classes annotated with @Component, @Service, @Repository and @Controller will be auto-detected.
2. The classes that name ends with Util will be auto detected.
3. The classes that name ends with DAO will not be auto detected even if the classes have been annotated with @Component, @Service, @Repository or @Controller.

When we run SpringFilterAnnotationDemo, we will get the output as follows.
Addition:45
No qualifying bean of type [com.concretepage.dao.BookDAO] is defined
No qualifying bean of type [com.concretepage.service.UserService] is defined 
Find the equivalent XML configuration of JavaConfig.
spring-config.xml
<context:component-scan base-package="com.concretepage">
	<context:include-filter type="aspectj" expression="com.concretepage..*Util+"/>
        <context:exclude-filter type="aspectj" expression="com.concretepage..*DAO+"/>		        
</context:component-scan> 
When we run SpringFilterXMLDemo, the output will be same as the output by JavaConfig.

Filter Type: regex

To use regex component scan filter type, find the JavaConfig.
AppConfig.java
package com.concretepage;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
@Configuration
@ComponentScan(basePackages = "com.concretepage",
     includeFilters = @Filter(type = FilterType.REGEX, pattern="com.concretepage.*.*Service"),
     excludeFilters = @Filter(type = FilterType.REGEX, pattern="com.concretepage.*.*DAO"))
public class AppConfig {

} 
Using above JavaConfig, we can achieve following points within the base package com.concretepage.
1. All classes annotated with @Component, @Service, @Repository and @Controller will be auto-detected.
2. The classes that name ends with Service will be auto detected.
3. The classes that name ends with DAO will not be auto detected even if the classes have been annotated with @Component, @Service, @Repository or @Controller.

When we run SpringFilterAnnotationDemo, we will get the output as follows.
No qualifying bean of type [com.concretepage.util.CalcUtil] is defined
No qualifying bean of type [com.concretepage.dao.BookDAO] is defined
User Role:admin 
Now find the XML configuration equivalent to JavaConfig.
spring-config.xml
<context:component-scan base-package="com.concretepage">
	<context:include-filter type="regex" expression="com.concretepage.*.*Service"/>
        <context:exclude-filter type="regex" expression="com.concretepage.*.*DAO"/>		        
</context:component-scan> 
When we run SpringFilterXMLDemo, the output will be same as the output by JavaConfig.

Using Different Filter Types Together

Now we will provide a JavaConfig example where we will use more than one filter type to include and exclude classes not to auto detect.
AppConfig.java
package com.concretepage;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Repository;
@Configuration
@ComponentScan(basePackages = "com.concretepage",
     includeFilters = @Filter(type = FilterType.REGEX, pattern="com.concretepage.*.*Util"),
     excludeFilters = @Filter(Repository.class))
public class AppConfig {

} 
Here we are using regex filter type to include classes and annotation filter type to exclude classes not to auto detect. Using above JavaConfig, we conclude following points within the base package com.concretepage.
1. All classes annotated with @Component, @Service and @Controller will be auto-detected.
2. The classes that name ends with Util will be auto detected.
3. The classed annotated with Repository stereo type will not be auto detected.

When we run SpringFilterAnnotationDemo, we will get the output as follows.
Addition:45
No qualifying bean of type [com.concretepage.dao.BookDAO] is defined
No qualifying bean of type [com.concretepage.service.UserService] is defined 
Find the XML configuration equivalent to JavaConfig.
spring-config.xml
>context:component-scan base-package="com.concretepage"<
	>context:include-filter type="regex" expression="com.concretepage.*.*Util"/<
        >context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/<		        
>/context:component-scan< 
When we run SpringFilterXMLDemo class, the output be the same as the output by JavaConfig.

Download Source Code

POSTED BY
ARVIND RAI
ARVIND RAI
LEARN MORE








©2024 concretepage.com | Privacy Policy | Contact Us