Mastering Spring Boot 3 @ComponentScan: Advanced Configurations & Examples

This article provides a comprehensive, step‑by‑step guide to using Spring Boot 3's @ComponentScan annotation, covering basic usage, package filtering, include/exclude filters, lazy initialization, custom name generators, scoped proxies, and custom scope resolvers, complete with runnable code samples and output screenshots.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Mastering Spring Boot 3 @ComponentScan: Advanced Configurations & Examples

1. Introduction

In Spring, the @ComponentScan annotation is a powerful tool for automatically detecting and registering beans annotated with @Component, @Service, @Repository, or @Controller. This article explores its hidden features and best practices.

2. Practical Cases

2.1 Basic Usage

With a simple @ComponentScan on the configuration class, Spring scans the current package and its sub‑packages, registering classes A, B, etc.

package com.pack.ioc.scan_component;
@Component
public class A {}

package com.pack.ioc.scan_component.child;
@Component
public class B {}

@Configuration
@ComponentScan
public class AppConfig {}
public class ComponentScanTest {
    public static void main(String[] args) {
        try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext()) {
            context.registerBean(AppConfig.class);
            context.refresh();
            System.out.println(Arrays.toString(context.getBeanDefinitionNames()));
        }
    }
}

Output shows both A and B are registered.

2.2 Specifying basePackages

@ComponentScan(basePackages = {"com.pack.ioc.scan_component.child"})
public class AppConfig {}

Only beans in the specified sub‑package ( B) are registered.

2.3 Specifying basePackageClasses

@ComponentScan(basePackageClasses = {B.class})
public class AppConfig {}

Scanning is performed based on the package of the given class ( B).

2.4 Using includeFilters

The excludeFilters and includeFilters attributes allow fine‑grained control. The FilterType enum provides the following values:

public enum FilterType {
    ANNOTATION,
    ASSIGNABLE_TYPE,
    ASPECTJ,
    REGEX,
    CUSTOM
}

2.4.1 ANNOTATION

@ComponentScan(includeFilters = @Filter(type = FilterType.ANNOTATION, classes = Pack.class))
public class AppConfig {}

Custom annotation @Pack is detected and its beans are registered.

2.4.2 ASPECTJ

@ComponentScan(includeFilters = @Filter(type = FilterType.ASPECTJ, pattern = {"com.pack.*Pack*"}))
public class AppConfig {}

2.4.3 ASSIGNABLE_TYPE

@ComponentScan(includeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {DAO.class}))
public class AppConfig {}

All classes implementing DAO are scanned.

2.4.4 REGEX

@ComponentScan(includeFilters = @Filter(type = FilterType.REGEX, pattern = {"com\\.pack\\..*Pack.*"}))
public class AppConfig {}

2.4.5 CUSTOM

public class PackTypeFilter implements TypeFilter {
    @Override
    public boolean match(MetadataReader mr, MetadataReaderFactory mf) throws IOException {
        return mr.getAnnotationMetadata().hasAnnotation(Pack.class.getName());
    }
}

@ComponentScan(includeFilters = @Filter(type = FilterType.CUSTOM, classes = {PackTypeFilter.class}))
public class AppConfig {}

2.5 Specifying lazyInit

@ComponentScan(lazyInit = true)
public class AppConfig {}

Beans are created lazily; initialization callbacks are not executed at context startup.

2.6 Specifying useDefaultFilters

@ComponentScan(useDefaultFilters = false, includeFilters = @Filter(type = FilterType.CUSTOM, classes = {PackTypeFilter.class}))
public class AppConfig {}

Only custom filters are applied; default @Component detection is disabled.

2.7 Specifying nameGenerator

public class PackBeanNameGenerator extends AnnotationBeanNameGenerator {
    @Override
    public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
        String beanName = super.generateBeanName(definition, registry);
        beanName = beanName.replaceFirst("^.", beanName.substring(0, 1).toUpperCase());
        return "pack" + beanName;
    }
}

@ComponentScan(nameGenerator = PackBeanNameGenerator.class)
public class AppConfig {}

All bean names receive the pack prefix.

2.8 Specifying scopedProxy

@Component
@Scope
public class A implements InitializingBean {}

@ComponentScan(scopedProxy = ScopedProxyMode.TARGET_CLASS)
public class AppConfig {}

The bean A is proxied using CGLIB.

2.9 Specifying scopeResolver

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface PackScope {
    @AliasFor("scopeName") String value() default "";
    @AliasFor("value") String scopeName() default "";
    ScopedProxyMode proxyMode() default ScopedProxyMode.DEFAULT;
}

public class PackAnnotationScopeMetadataResolver extends AnnotationScopeMetadataResolver {
    public PackAnnotationScopeMetadataResolver() {
        setScopeAnnotationType(PackScope.class);
    }
}

@PackScope(proxyMode = ScopedProxyMode.TARGET_CLASS)
@Component
public class A implements InitializingBean {}

Custom scope annotation and resolver are applied successfully.

Conclusion

The article covered every aspect of the @ComponentScan annotation, including package selection, filter types, lazy initialization, custom bean name generation, scoped proxies, and custom scope resolution, providing a solid foundation for advanced Spring Boot configuration.

ComponentScan output
ComponentScan output
Lazy init result
Lazy init result
Scoped proxy result
Scoped proxy result
Custom scope resolver result
Custom scope resolver result
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Backend DevelopmentSpring BootComponentScanSpring Framework
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.