版本:SpringBoot 2.1.7.RELEASE
1 @ComponentScan的作用
@ComponentScan
注解是用来告诉Spring框架应该去哪里扫描被@Component
注解注释的类,并将这些类注册成Spring容器中的bean的。
@ComponentScan
注解通常与@Configuration
注解一起使用。
2 @ComponentScan源码分析
@ComponentScan
的源码如下:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {
/**
* 扫描bean的包路径,可以是单个包路径,也可以是数组。
* 不指定,默认是扫描被这个注解注释的类所在的包及其子包路径下的bean。
* 例如:"org.my.pkg"。
*/
@AliasFor("basePackages")
String[] value() default {};
/**
* 和value一样。
* 扫描bean的包路径,可以是单个包路径,也可以是数组。
* 不指定,默认是扫描被这个注解注释的类所在的包及其子包路径下的bean。
* 例如:"org.my.pkg"。
*/
@AliasFor("value")
String[] basePackages() default {};
/**
* 指定被扫描的类的Class对象。
*/
Class<?>[] basePackageClasses() default {};
/**
* bean名称生成器,用于命名被扫描到并注册成Spring容器中的bean的bean名称。
*/
Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
/**
* scope解析器,解析被检测到的bean的scope。
*/
Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;
/**
* 指明在扫描bean的时候是否需要生成scope代理。
*/
ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;
/**
* 控制扫描的类规则,可以考虑使用includeFilters和excludeFilters进行更加灵活的控制。
*/
String resourcePattern() default ClassPathScanningCandidateComponentProvider.DEFAULT_RESOURCE_PATTERN;
/**
* 指明是否自动的扫描被@Component、@Repository、@Service、@Controller注解的类,默认为true。
*/
boolean useDefaultFilters() default true;
/**
* 指定哪些类被扫描到。
* 通过过滤器缩小basePackages指定扫描的类的范围。
* 注意:
* 如果指定了这些过滤器,那么除了默认过滤器会生效之外,这些过滤器也会生效;
* 任何在basePackages下的类,只要满足这些指定的过滤器的规则,那么都将会被扫描,
* 即使是没有满足默认过滤器的规则(比如说,没有使用@Component进行注解)。
*/
Filter[] includeFilters() default {};
/**
* 指定哪些类不要被扫描到。
*/
Filter[] excludeFilters() default {};
/**
* 指定那些被扫描到的bean是否要进行懒加载,默认是false。
*/
boolean lazyInit() default false;
......
}
@ComponentScan
中有很多可以使用的属性,用的比较多的就是:
- basePackages
- includeFilters
- excludeFilters
3 @Filter源码分析
在需要使用includeFilters
和excludeFilters
的时候,需要传入@Filter
数组,例如在SpringBoot中这样使用:
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class)
})
@Filter
就是来描述一个个的过滤规则的。
在看@Filter
源码之前,先看下FilterType
源码,这是来定义过滤器的类型的:
public enum FilterType {
/**
* 按注解过滤,筛选被指定注解注释的项。
* @see org.springframework.core.type.filter.AnnotationTypeFilter
*/
ANNOTATION,
/**
* 按指定类型过滤,筛选指定类型的项。
* @see org.springframework.core.type.filter.AssignableTypeFilter
*/
ASSIGNABLE_TYPE,
/**
* 按AspectJ表达式过滤
* @see org.springframework.core.type.filter.AspectJTypeFilter
*/
ASPECTJ,
/**
* 按正则表达式过滤
* @see org.springframework.core.type.filter.RegexPatternTypeFilter
*/
REGEX,
/**
* 按照自定义规则过滤,规则类必须实现TypeFilter接口。
* {@link org.springframework.core.type.filter.TypeFilter} implementation.
*/
CUSTOM
}
下面来看下@Filter
的源码:
@Retention(RetentionPolicy.RUNTIME)
@Target({})
@interface Filter {
/**
* Filter的类型,默认是lterType.ANNOTATION,按照注解来过滤。
*/
FilterType type() default FilterType.ANNOTATION;
/**
* 和classes一样。
*/
@AliasFor("classes")
Class<?>[] value() default {};
/**
* 作为过滤器的类或者类数组。(详细解析见后文)
*/
@AliasFor("value")
Class<?>[] classes() default {};
/**
* 匹配模式(表达式)。
* 如果type的值为FilterType.ASPECTJ,那么pattern的值就是AspectJ表达式。
* 如果type的值为FilterType.REGEX,那么pattern的值就是正则表达式。
*/
String[] pattern() default {};
}
classes
属性的含义:
-
用来指定作为过滤器的类或者类数组。
-
classes
属性指定的值的含义与type
属性指定的类型有关,下表是他们之间的关系:
FilterType | Class Interpreted As |
---|---|
ANNOTATION | 注解本身 |
ASSIGNABLE_TYPE | 被扫描的类型 |
CUSTOM | TypeFilter的一个实现类 |