In this article “Spring @ComponentScan Annotation Example” I have listed the following. Spring needs to know the packages to scan for annotated components. We can use @ComponentScan
annotation to specify the base packages to scan. Any class which is annotated with @Component
will be scanned for registered. Even classes annotated with @Configuration
are candidates for component scanning as @Configuration
annotation is meta-annotated with @Component
.
If specific packages are not defined, scanning will occur from the package of the class that declares this annotation.
The corresponding element that provides component scanning using Spring XML is <context:component-scan> element.
In this article we will see examples of @ComponentScan
.
Package Structure
In our example, we have multiple packages defined, packageA, packageB, packageC, packageD and packageE. Each package contains one or more components.
com.javarticles.spring.annotations.packageA:
BeanA:
package com.javarticles.spring.annotations.packageA; import org.springframework.stereotype.Component; @Component public class BeanA { }
com.javarticles.spring.annotations.packageB:
BeanB:
package com.javarticles.spring.annotations.packageB; import org.springframework.stereotype.Component; @Component public class BeanB { }
com.javarticles.spring.annotations.packageC:
BeanC1:
package com.javarticles.spring.annotations.packageC; import org.springframework.stereotype.Component; @Component public class BeanC1 { }
BeanC2:
package com.javarticles.spring.annotations.packageC; import org.springframework.stereotype.Component; @Component public class BeanC2 { }
BeanC3:
package com.javarticles.spring.annotations.packageC; import org.springframework.stereotype.Component; @Component public class BeanC3 { }
com.javarticles.spring.annotations.packageD:
BeanD:
package com.javarticles.spring.annotations.packageD; import org.springframework.stereotype.Component; @Component public class BeanD { }
com.javarticles.spring.annotations.packageE:
BeanE1:
package com.javarticles.spring.annotations.packageE; import org.springframework.stereotype.Component; @Component public class BeanE1 { }
BeanE2:
package com.javarticles.spring.annotations.packageE; import org.springframework.stereotype.Component; @Component @Custom public class BeanE2 { }
Custom:
package com.javarticles.spring.annotations.packageE; public @interface Custom { }
@ComponentScan – Identifying Base Packages
You can provide the package names in attribute basePackages
. You can also provide one of the class from the package using basePackageClasses
and spring can derive the package name from the class included in the attribute. Instead of the basePackages
, you can use its alias value
to specific packages to scan. You can’t include both value
and basePackages
.
SpringComponentScanAnnotationExample:
package com.javarticles.spring.annotations; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import com.javarticles.spring.annotations.packageC.BeanC1; @Configuration @ComponentScan(basePackages = { "com.javarticles.spring.annotations.packageA", "com.javarticles.spring.annotations.packageB", "com.javarticles.spring.annotations.packageE" }, basePackageClasses = BeanC1.class) public class SpringComponentScanAnnotationExample { public static void main(String[] args) { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); try { ctx.register(SpringComponentScanAnnotationExample.class); ctx.refresh(); System.out.println("SpringComponentScanAnnotationExample: " + ctx.getBean("springComponentScanAnnotationExample")); System.out.println("BeanA: " + ctx.getBean("beanA")); System.out.println("BeanB: " + ctx.getBean("beanB")); System.out.println("BeanC1: " + ctx.getBean("beanC1")); System.out.println("BeanC2: " + ctx.getBean("beanC2")); System.out.println("Contains BeanC3?: " + ctx.containsBean("beanC3")); System.out.println("Contains BeanD?: " + ctx.containsBean("beanD")); System.out.println("Contains BeanE1?: " + ctx.containsBean("beanE1")); System.out.println("Contains BeanE2?: " + ctx.containsBean("beanE2")); } finally { ctx.close(); } } }
Since packageD is not included so class from packageD are not registered.
Output:
Jan 26, 2016 11:04:17 AM org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh INFO: Refreshing org.spring[email protected]4783da3f: startup date [Tue Jan 26 11:04:17 IST 2016]; root of context hierarchy Jan 26, 2016 11:04:17 AM org.springframework.context.annotation.AnnotationConfigApplicationContext doClose INFO: Closing org.spring[email protected]4783da3f: startup date [Tue Jan 26 11:04:17 IST 2016]; root of context hierarchy SpringComponentScanAnnotationExample: com.javarticles.spring.annotations.Spring[email protected]2bea5ab4 BeanA: [email protected] BeanB: [email protected] BeanC1: [email protected] BeanC2: [email protected] Contains BeanC3?: true Contains BeanD?: false Contains BeanE1?: true Contains BeanE2?: true
Disabling Default Filters
The default filter automatically detects the components from the list of base packages specified. You can disable this behavior using attribute useDefaultFilters
.
SpringComponentScanDisableDefaultFiltersExample:
package com.javarticles.spring.annotations; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @Configuration @ComponentScan(value="com.javarticles.spring.annotations.packageA", useDefaultFilters=false) public class SpringComponentScanDisableDefaultFiltersExample { public static void main(String[] args) { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); try { ctx.register(SpringComponentScanDisableDefaultFiltersExample.class); ctx.refresh(); System.out.println("Contains BeanA?: " + ctx.containsBean("beanA")); } finally { ctx.close(); } } }
Output:
Jan 26, 2016 11:07:36 AM org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh INFO: Refreshing org.spring[email protected]4783da3f: startup date [Tue Jan 26 11:07:36 IST 2016]; root of context hierarchy Contains BeanA?: false Jan 26, 2016 11:07:36 AM org.springframework.context.annotation.AnnotationConfigApplicationContext doClose INFO: Closing org.spring[email protected]4783da3f: startup date [Tue Jan 26 11:07:36 IST 2016]; root of context hierarchy
Exclude Filters
If you want exclude one or more classes, you can do that using excludeFilters
. Use the nested annotation @ComponentScan.Filter
to specify what is to be excluded.
In the below example, we exclude BeanC3
class. You can also filter candidates marked with a given annotation or write your own custom filter. The custom filter has to implement TypeFilter
.
SpringComponentScanExcludeAnnotationExample:
package com.javarticles.spring.annotations; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.FilterType; import com.javarticles.spring.annotations.packageC.BeanC1; import com.javarticles.spring.annotations.packageC.BeanC3; @Configuration @ComponentScan(basePackageClasses = BeanC1.class, excludeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = BeanC3.class)) public class SpringComponentScanExcludeAnnotationExample { public static void main(String[] args) { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); try { ctx.register(SpringComponentScanExcludeAnnotationExample.class); ctx.refresh(); System.out.println("Contains BeanC1?: " + ctx.containsBean("beanC1")); System.out.println("Contains BeanC2?: " + ctx.containsBean("beanC2")); System.out.println("Contains BeanC3?: " + ctx.containsBean("beanC3")); } finally { ctx.close(); } } }
Output:
Jan 26, 2016 11:09:48 AM org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh INFO: Refreshing org.spring[email protected]4783da3f: startup date [Tue Jan 26 11:09:48 IST 2016]; root of context hierarchy Contains BeanC1?: true Contains BeanC2?: true Contains BeanC3?: false Jan 26, 2016 11:09:48 AM org.springframework.context.annotation.AnnotationConfigApplicationContext doClose INFO: Closing org.spring[email protected]4783da3f: startup date [Tue Jan 26 11:09:48 IST 2016]; root of context hierarchy
Include Filters
We also have an attribute called includeFilters
. In order for this to work, you need to specify the base packages, disable the default filters and explicitly include the components using @ComponentScan.Filter
.
In the below example, we only want to include component annotated with @Custom
.
SpringComponentScanIncludeAnnotationExample:
package com.javarticles.spring.annotations; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.FilterType; import com.javarticles.spring.annotations.packageE.Custom; @Configuration @ComponentScan(basePackages = { "com.javarticles.spring.annotations.packageB", "com.javarticles.spring.annotations.packageE" }, includeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, value = Custom.class), useDefaultFilters = false) public class SpringComponentScanIncludeAnnotationExample { public static void main(String[] args) { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); try { ctx.register(SpringComponentScanIncludeAnnotationExample.class); ctx.refresh(); System.out.println("Contains BeanB?: " + ctx.containsBean("beanB")); System.out.println("Contains BeanE1?: " + ctx.containsBean("beanE1")); System.out.println("Contains BeanE2?: " + ctx.containsBean("beanE2")); } finally { ctx.close(); } } }
Output:
Jan 26, 2016 11:11:03 AM org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh INFO: Refreshing org.spring[email protected]4783da3f: startup date [Tue Jan 26 11:11:03 IST 2016]; root of context hierarchy Contains BeanB?: false Contains BeanE1?: false Contains BeanE2?: true Jan 26, 2016 11:11:03 AM org.springframework.context.annotation.AnnotationConfigApplicationContext doClose INFO: Closing org.spring[email protected]4783da3f: startup date [Tue Jan 26 11:11:03 IST 2016]; root of context hierarchy
Trigger ComponentScan via XML
In the below example, we bootstrap the configuration using spring XML file.
applicationContext.xml:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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-3.1.xsd"> <context:annotation-config/> <bean class="com.javarticles.spring.annotations.SpringComponentScanAnnotationViaXMLExample"/> </beans>
SpringComponentScanAnnotationViaXMLExample:
package com.javarticles.spring.annotations; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.support.ClassPathXmlApplicationContext; @Configuration @ComponentScan(basePackages = { "com.javarticles.spring.annotations.packageA", "com.javarticles.spring.annotations.packageB" }) public class SpringComponentScanAnnotationViaXMLExample { public static void main(String[] args) { ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); try { System.out.println("BeanA: " + ctx.getBean("beanA")); System.out.println("BeanB: " + ctx.getBean("beanB")); System.out.println("Contains BeanC1?: " + ctx.containsBean("beanC31")); System.out.println("Contains BeanD?: " + ctx.containsBean("beanD")); System.out.println("Contains BeanE1?: " + ctx.containsBean("beanE1")); } finally { ctx.close(); } } }
Output:
Jan 26, 2016 11:20:36 AM org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh INFO: Refreshing org[email protected]1f17ae12: startup date [Tue Jan 26 11:20:36 IST 2016]; root of context hierarchy Jan 26, 2016 11:20:37 AM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions INFO: Loading XML bean definitions from class path resource [applicationContext.xml] BeanA: [email protected] BeanB: com.javarticles[email protected] Contains BeanC1?: false Contains BeanD?: false Contains BeanE1?: false Jan 26, 2016 11:20:37 AM org.springframework.context.support.ClassPathXmlApplicationContext doClose INFO: Closing org[email protected]1f17ae12: startup date [Tue Jan 26 11:20:36 IST 2016]; root of context hierarchy
Download the source code
This was an example about spring @ComponentScan annotation.