Spring Component Scan Include and Exclude Filter Example
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.
Contents
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))
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 { }
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; } }
@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"; } }
@ComponentScan
. Find the UserService
.
UserService.java
package com.concretepage.service; public class UserService { public String getUserRole() { return "admin"; } }
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 { }
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(); } }
Addition:45 No qualifying bean of type [com.concretepage.dao.BookDAO] is defined No qualifying bean of type [com.concretepage.service.UserService] is defined
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>
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(); } }
Filter Type: assignable
To use assignable, we are creating two interfaces.IUserService.java
package com.concretepage.service; public interface IUserService { String getUserRole(); }
UserService
class.
UserService.java
package com.concretepage.service; public class UserService implements IUserService { @Override public String getUserRole() { return "admin"; } }
ICalcUtil.java
package com.concretepage.util; public interface ICalcUtil { int addNumbers(int num1, int num2); }
CalcUtil
class.
CalcUtil.java
package com.concretepage.util; public class CalcUtil implements ICalcUtil { @Override public int addNumbers(int num1, int num2) { return num1 + num2; } }
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 { }
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
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>
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 { }
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
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>
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 { }
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
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>
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 { }
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
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<
SpringFilterXMLDemo
class, the output be the same as the output by JavaConfig.