Introduction:
A Classpath scanning basically means, detecting the classes that need to be managed by the Spring under a specified package. You need to make use of the spring @ComponentScan annotation with the @Configuration for classpath scanning. This annotation allows you to specify a base package and also a filter if needed to fine control the package scanning. We will look into both the approaches in this article.
Inside look at @ComponentScan annotation
Before learning to use this annotation, let us take a look at this annotation and understand the parameters it accepts. I have highlighted the most used parameters.
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {
@AliasFor("basePackages")
String[] value() default {};
@AliasFor("value")
String[] basePackages() default {};
Class<?>[] basePackageClasses() default {};
Class<? extends BeanNameGenerator> nameGenerator()
default BeanNameGenerator.class;
Class<? extends ScopeMetadataResolver> scopeResolver()
default AnnotationScopeMetadataResolver.class;
ScopedProxyMode scopedProxy()
default ScopedProxyMode.DEFAULT;
String resourcePattern() default
ClassPathScanningCandidateComponentProvider.DEFAULT_RESOURCE_PATTERN;
/**
* Indicates whether automatic detection of classes annotated with
* {@code @Component} {@code @Repository}, {@code @Service},
* or {@code @Controller} should be enabled.
*/
boolean useDefaultFilters() default true;
Filter[] includeFilters() default {};
Filter[] excludeFilters() default {};
boolean lazyInit() default false;
}
We will explore each of these, will use @ComponentScan without specifying basePackages value, then use it with a base package value. After this, we will also learn to use custom filters.
Use the @ComponentScan annotation
- The
@ComponentScan
can be used along with the XML<context:component-scan base-package=""/>
configuration.
1. Use @ComponentScan with arguments
The simple way to use this annotation is to use it with the @Configuration or with the application configuration class and specify the base package in it. GitHub link to the below code.
package basic.ioc.autowire;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("basic.ioc.autowire")
public class AutowireBeanConfig {
//Other configs inside.
}
It is also possible to provide a list of base classes as shown below.
@Configuration
@ComponentScan(basePackages = {"basic.ioc.autowire", "basic.ioc.setter"})
public class AutowireBeanConfig {
//other configs
}
2. Use @ComponentScan without an argument
Like mentioned before, it is optional to specify the basePackage value. When used without an argument, you will have less control over the package scanning.
@Configuration
@ComponentScan
public class DemoAppConfig {
//...
}
NOTE: The location where @ComponentScan is put, the scanning starts from its package by default.
3. Use @ComponentScan in a Spring-Boot application
In a Spring-Boot application, we don’t need to specify the @Configuration annotation unless we want more control over the classpath scanning. This is because of the @SpringBootApplication
, which is already a combination of below listed three annotations.
@Configuration
@EnableAutoConfiguration
@ComponentScan
In a typical Spring-Boot app the @SpringBootApplication
annotation is present in a base level package, hence everything under that package gets auto-detected.
4. Use Filters with @ComponentScan
The default filters in @ComponentScan
effectively detects the stereotype annotations – @Component, @Repository, @Service, @Controller, @RestController, and the meta-annotation @Configuration. It is also possible to disable this default filter as below.
@ComponentScan(basePackages = "com.jbd.app", useDefaultFilters=false)
Let’s say we want to disable the detection of @Repository annotated class, instead include the classes that have a Dao
in their name e.g. StudentDao.
@Configuration
@ComponentScan(basePackages = "com.jbd",
includeFilters = @Filter(type = FilterType.REGEX, pattern = ".*Dao"),
excludeFilters = @Filter(Repository.class))
public class AppConfig {
...
}
It is also possible to have the same in XML based configurations.
<beans>
<context:component-scan base-package="com.jbd">
<context:include-filter type="regex"
expression=".*Dao"/>
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Repository"/>
</context:component-scan>
</beans>
Conclusion:
I have explained the ways in which you can use the @ComponentScan annotation to auto scan the classes and manage them as beans in Spring.