Spring @ComponentScan Annotation Example

0

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.

Package Structure

Package Structure

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 valueto 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: [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.

You can download the source code here: springComponentScanAnnotationExample.zip
Share.

Comments are closed.