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.

ComponentScan
@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.

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

Java
@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.

Java
@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.

Java
@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.

Java
@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.

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

By |Last Updated: April 2nd, 2024|Categories: Spring Framework|