【SpringBoot笔记15】@ComponentScan源码分析

版本: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源码分析

在需要使用includeFiltersexcludeFilters的时候,需要传入@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的一个实现类
发布了178 篇原创文章 · 获赞 152 · 访问量 61万+

猜你喜欢

转载自blog.csdn.net/hbtj_1216/article/details/99131857