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
The code snippet given as example for basePackageClasses() is actually just another example for basePackages. It should be corrected to e.g.
@ComponentScan(basePackageClasses = {"com.bsmlabs.microservices.movie", "com.bsmlabs.microservices.payment"})
public class MovieApplication {
}
And the explanation for “scopedProxy” says that “developers should create proxies” – it should probably be “the framework” or “ApplicationContext” instead of developers.
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
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.