Do you want your ad here?

Contact us to get your ad seen by thousands of users every day!

[email protected]

Spring: Internals of @ComponentScan

  • August 20, 2024
  • 4300 Unique Views
  • 3 min read
Table of Contents
Attributes used with ComponentScan annotationConclusionReference

The @ComponentScan annotation, which is an interface located within the org.springframework.context.annotation package, facilitates component scanning in a Spring application. This allows the Spring Container to automatically detect beans.

Spring automatically identifies Java classes that developers mark with stereotypes like @Configuration, @Component, @Service, @Controller, and @Repository. Developers can annotate the component scan with or without parameters.

You can designate either basePackageClasses() or basePackages() (or its equivalent value()) to identify the specific packages that need to be scanned.

The @ComponentScan annotation, when used without any arguments, instructs Spring to scan the current package and all its sub-packages.

For instance:

import org.springframework.context.annotation.ComponentScan;
@ComponentScan
public class MovieApplication {
}

The @ComponentScan annotation instructs Spring to perform a scan of the specified package when you provide it with arguments, as indicated by the basePackages attribute. For instance:

import org.springframework.context.annotation.ComponentScan;

@ComponentScan(basePackages = "com.bsmlabs.microservices")
public class MovieApplication {}

The @ComponentScan annotation acts as a substitute for the <context:component-scan/> XML tag. While it includes an annotation-config attribute, the XML version lacks this feature. In most scenarios where developers utilize @ComponentScan, they presume that default annotation configuration processing is in effect, such as the handling of @Autowired.

The component scan interface looks like

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {
}

Since the RetentionPolicy of ComponentScan is Runtime, it will only execute during the runtime phase. You can apply this annotation at the class level, as well as at the interface or enum declaration levels. Therefore, you specify its @Target as ElementType with Type, specifically @Target(ElementType.TYPE).

In the SpringBootApplication class, specifies the @ComponentScan annotation at the class level to enable component scanning at runtime which helps to create

  • ApplicationContext()
  • Register Environment
  • Loads Beans Definitions
  • Applying the ApplicationContextInitializer and ApplicationContextInitilizerEvent
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
        @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {

}

Attributes used with ComponentScan annotation

The value() function acts as an alias for basePackages, allowing developers to make more specific annotation declarations when they do not require additional attributes. For instance, developers can use @ComponentScan("com.bsmlabs.microservices") as an alternative to @ComponentScan(basePackages = "com.bsmlabs.microservices").

@AliasFor("basePackages")
String[] value() default {};

The basePackages() identifies annotated components, using the value as an alias for this attribute. To find a type-safe alternative to Spring-based package names, one can employ basePackageClasses.

@AliasFor("value")
String[] basePackages() default {};

For example:

import org.springframework.context.annotation.ComponentScan;
@ComponentScan(basePackages = "com.bsmlabs.microservices")
public class MovieApplication {
}

The basePackageClasses() method outlines the process of scanning all packages that contain annotated components. This indicates that the scanning procedure will be applied to the package associated with each specified class.

For example:

import org.springframework.context.annotation.ComponentScan;
@ComponentScan(basePackageClasses = {"com.bsmlabs.microservices.movie", "com.bsmlabs.microservices.payment"})
public class MovieApplication {
}

nameGenerator(): The Spring container specifically designates the BeanNameGenerator class for assigning names to the components it identifies within the ApplicationContext.

Class<? extends BeanNameGenerator> nameGenerator()
default BeanNameGenerator.class;

The inherent value of the BeanNameGenerator interface signifies that the scanner responsible for processing the @ComponentScan annotation should use its inherited bean name generator.

Default AnnotationBeanNameGenerator or any custom instance supplied to the application context at startup or bootstrap time.

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FullyQualifiedAnnotationBeanNameGenerator;

@ComponentScan(nameGenerator = FullBeanNameGenerator.class)
public class MovieApplication {
}

scopeResolver: The ScopeMetadataResolver is utilized for determining the scope of identified components.

Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;

For example:

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ScopedProxyMode;

@ComponentScan(basePackages = "com.bsmlabs.microservices", scopeResolver = MyResolverBean.class)
public class MovieApplication {
}

scopedProxy: This specifies whether spring framework should create proxies for identified components, which may be essential when they employ scopes in a proxy-oriented manner.

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ScopedProxyMode;

@ComponentScan(basePackages = "com.bsmlabs.microservices", scopedProxy = ScopedProxyMode.DEFAULT)
public class MovieApplication {
}

useDefaultFilters: This specifies the automatic detection of classes that are annotated with @Component, @Controller, @Service, and @Repository. The values can be set to either false or true, with the default being true.

boolean useDefaultFilters() default true;

For example:

import org.springframework.context.annotation.ComponentScan;
@ComponentScan(basePackages = "com.bsmlabs.microservices", useDefaultFilters = false)
public class MovieApplication {
}

includeFilters: It delineates the types that qualify for component scanning.

Filter[] includeFilters() default {};

For example:

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType;

@ComponentScan(basePackages = "com.bsmlabs.microservices", includeFilters = @ComponentScan.Filter(type= FilterType.ANNOTATION))
public class MovieApplication {
}

5 Types of filter available for ComponentScan.Filter

  • FilterType.ANNOTATION : Filter candidates marked with a given annotations. It is part of package org.springframework.core.type.filter.AnnotationTypeFilter
  • FilterType.ASSIGNABLE_TYPE: Filter candidates assignable to a given type. It is part of package org.springframework.core.type.filter.AssignableTypeFilter
  • FilterType.ASPECTJ: Filter candidates matches a given AspectJ type pattern expression. It is part of package org.springframework.core.type.filter.AspectJTypeFilter
  • FilterType.REGEX: Filter candidates matching a given regex pattern. It is part of package org.springframework.core.type.filter.RegexPatternTypeFilter
  • FilterType.CUSTOM: Filter candidates using a given custom org.springframework.core.type.filter.TypeFilter

excludeFilters: It specifies which types are not eligible for component scanning.

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType;

@ComponentScan(basePackages = "com.bsmlabs.microservices", excludeFilters = @ComponentScan.Filter(type= FilterType.REGEX))
public class MovieApplication {
}

lazyInit(): It specifies whether scanned beans should be registered for lazy initiation.

Conclusion

The `@ComponentScan` annotation streamlines the configuration process of Spring applications by minimizing the need for developers to manually define beans, promoting a convention-over-configuration methodology, and ensuring that the application context contains the essential components.

Reference

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/ComponentScan.html

Do you want your ad here?

Contact us to get your ad seen by thousands of users every day!

[email protected]

Comments (6)

Highlight your code snippets using [code lang="language name"] shortcode. Just insert your code between opening and closing tag: [code lang="java"] code [/code]. Or specify another language.

Samot avatar

Samot

5 months ago

Clickbait. This has nothing to do with the "internals". There are few things that could be less "internal" than the PUBLIC API of the ComponenScan annotation.

Highlight your code snippets using [code lang="language name"] shortcode. Just insert your code between opening and closing tag: [code lang="java"] code [/code]. Or specify another language.

Mahendra Rao B avatar

Mahendra Rao B

5 months ago

Thanks for your feedback.

Highlight your code snippets using [code lang="language name"] shortcode. Just insert your code between opening and closing tag: [code lang="java"] code [/code]. Or specify another language.

Java Weekly, Issue 557 | Baeldung

5 months ago

[…] >> Spring: Internals of @ComponentScan [foojay.io] […]

Highlight your code snippets using [code lang="language name"] shortcode. Just insert your code between opening and closing tag: [code lang="java"] code [/code]. Or specify another language.

Mahendra Rao B avatar

Mahendra Rao B

5 months ago

Thanks Baeldung team for featuring my article in your newsletter.

Highlight your code snippets using [code lang="language name"] shortcode. Just insert your code between opening and closing tag: [code lang="java"] code [/code]. Or specify another language.

Fantaman avatar

Fantaman

5 months ago

The code snippet given as example for basePackageClasses() is actually just another example for basePackages. It should be corrected to e.g. [code lang="language name"] @ComponentScan(basePackageClasses = {"com.bsmlabs.microservices.movie", "com.bsmlabs.microservices.payment"}) public class MovieApplication { } [/code] And the explanation for "scopedProxy" says that "developers should create proxies" - it should probably be "the framework" or "ApplicationContext" instead of developers.

Highlight your code snippets using [code lang="language name"] shortcode. Just insert your code between opening and closing tag: [code lang="java"] code [/code]. Or specify another language.

Mahendra Rao B avatar

Mahendra Rao B

5 months ago

I sincerely appreciate your time in reviewing my article and offering your feedback, Fantaman. I acknowledge that I initially overlooked certain aspects, but I have now made the necessary corrections as requested. Thanks, Mahendra

Highlight your code snippets using [code lang="language name"] shortcode. Just insert your code between opening and closing tag: [code lang="java"] code [/code]. Or specify another language.

Subscribe to foojay updates:

https://foojay.io/feed/
Copied to the clipboard