Spring Boot注解全攻略(十):@ComponentScan

977 阅读1分钟

前言

之前提到,标注了@Component等注解的类会被注册为Bean。那么@ComponentScan自然就是用于开启包扫描,将Bean注册到Spring IoC环境中的注解。该注解标注在启动类上,它定义了扫描路径,从中找到标识了需要装配的类,自动将其装配到环境中。

在Spring Boot中,我们常常见到的是复合注解@SpringBootApplication,这个注解的功能之一等效于使用了@ComponentScan,因此我们前面没有显式提到要使用@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 "**/*.class";

    boolean useDefaultFilters() default true;

    ComponentScan.Filter[] includeFilters() default {};

    ComponentScan.Filter[] excludeFilters() default {};

    boolean lazyInit() default false;

    @Retention(RetentionPolicy.RUNTIME)
    @Target({})
    public @interface Filter {
        FilterType type() default FilterType.ANNOTATION;

        @AliasFor("classes")
        Class<?>[] value() default {};

        @AliasFor("value")
        Class<?>[] classes() default {};

        String[] pattern() default {};
    }
}

使用

@ComponentScan标注在启动类上,如果不传入basePackages属性,那么扫描的路径默认为当前包以及当前路径下的子包,这也是启动类为什么一般放在源代码最外层的原因。

@ComponentScan
public class MyApplication {
    // 启动类
}

includeFilters和excludeFilters两个属性的行为比较理解,就是包含或者排除哪些特殊情况,但Filter类值得讲一讲。
FilterType有五种类型:注解类型FilterType.ANNOTATION, 指定固定类FilterType.ASSIGNABLE_TYPE, 切入点类型FilterType.ASPECTJ, 正则表达式FilterType.REGEX, 自定义类型FilterType.CUSTOM
首先说注解类型,比如我们知道@Controller会被注册为Bean,我们可以将其排除。

@ComponentScan(
    excludeFilters={@Filter(type=FilterType.ANNOTATION,classes={Controller.class})}
)
public class MyApplication {
    // 启动类
}

使用includeFilters将未标注的自定义类注册进容器:

@ComponentScan(
    includeFilters={@Filter(type=FilterType.ASSIGNABLE_TYPE, classes={MyClass.class})}
)
public class MyApplication {
    // 启动类
}