SpringBoot - @ComponentScan注解使用详解

写在前面

SpringBoot - @Configuration注解使用详解
SpringBoot - 向容器中注册组件的方法有哪些?
SpringBoot - 如何查看Spring上下文中加载的Bean

@ComponentScan注解的作用是什么?

@ComponentScan主要用于将指定包路径下的、带有特定注解的对象自动装配到Spring容器中。ComponentScan会把正确标注@Component注解的对象进行自动装配。除了@Component外,还有@Controller、@Repository、@Service也标注了@Component注解。
简单来讲:在Spring中通过定义bean的注解定义了一些bean,而Spring并不知道除非你告诉它去可以找到它们,而@ComponentScan的作用就是告诉Spring去哪个路径下可以找到这些bean。

@ComponentScan注解如何使用?

@ComponentScan注解可以定义在接口、类、枚举、注解上。有以下几个常用属性:

  • [1] basePackages:定义待扫描的包路径名
  • [2] basePackageClasses:定义待扫描的类名
  • [3] includeFilters: 满足过滤器条件的,才能被扫描
  • [4] excludeFilters:满足过滤器条件的,不会被扫描

注意:includeFilters和excludeFilters都需要借助@ComponentScan.Filter来完成相应的扫描规则,FilterType有以下几个可选项:

  • [1] ANNOTATION(默认注解类型)
  • [2] ASSIGNABLE_TYPE(指定固定类)
  • [3] ASPECTJ(ASPECTJ类型)
  • [4] REGEX(正则表达式)
  • [5] CUSTOM(自定义类型),自定义的Filter需要实现TypeFilter接口
@ComponentScan(
    includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Service.class})},
    excludeFilters = {@ComponentScan.Filter(type = FilterType.CUSTOM, classes = MyExcludeFilter.class)}
)

@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 {};

	/**
	 * The {@link BeanNameGenerator} class to be used for naming detected components
	 * within the Spring container.
	 * 

The default value of the {@link BeanNameGenerator} interface itself indicates * that the scanner used to process this {@code @ComponentScan} annotation should * use its inherited bean name generator, e.g. the default * {@link AnnotationBeanNameGenerator} or any custom instance supplied to the * application context at bootstrap time. * @see AnnotationConfigApplicationContext#setBeanNameGenerator(BeanNameGenerator) * @see AnnotationBeanNameGenerator * @see FullyQualifiedAnnotationBeanNameGenerator */ Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class; /** * The {@link ScopeMetadataResolver} to be used for resolving the scope of detected components. */ Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class; /** * Indicates whether proxies should be generated for detected components, which may be * necessary when using scopes in a proxy-style fashion. *

The default is defer to the default behavior of the component scanner used to * execute the actual scan. *

Note that setting this attribute overrides any value set for {@link #scopeResolver}. * @see ClassPathBeanDefinitionScanner#setScopedProxyMode(ScopedProxyMode) */ ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT; // 指定符合组件检测条件的类文件, 默认是包扫描下的"**/*.class" String resourcePattern() default ClassPathScanningCandidateComponentProvider.DEFAULT_RESOURCE_PATTERN; // 是否开启对标注了@Component, @Repository, @Service, @Controller注解的类进行检测。 boolean useDefaultFilters() default true; // 包含的过滤条件 Filter[] includeFilters() default {}; // 排除的过滤条件 Filter[] excludeFilters() default {}; /** * Specify whether scanned beans should be registered for lazy initialization. *

Default is {@code false}; switch this to {@code true} when desired. * @since 4.1 */ boolean lazyInit() default false; /** * Declares the type filter to be used as an {@linkplain ComponentScan#includeFilters * include filter} or {@linkplain ComponentScan#excludeFilters exclude filter}. */ @Retention(RetentionPolicy.RUNTIME) @Target({}) @interface Filter { /** * The type of filter to use. *

Default is {@link FilterType#ANNOTATION}. * @see #classes * @see #pattern */ FilterType type() default FilterType.ANNOTATION; /** * Alias for {@link #classes}. * @see #classes */ @AliasFor("classes") Class<?>[] value() default {}; /** * The class or classes to use as the filter. *

The following table explains how the classes will be interpreted * based on the configured value of the {@link #type} attribute. *

* * * * * * * *
{@code FilterType}Class Interpreted As
{@link FilterType#ANNOTATION ANNOTATION}the annotation itself
{@link FilterType#ASSIGNABLE_TYPE ASSIGNABLE_TYPE}the type that detected components should be assignable to
{@link FilterType#CUSTOM CUSTOM}an implementation of {@link TypeFilter}
*

When multiple classes are specified, OR logic is applied * — for example, "include types annotated with {@code @Foo} OR {@code @Bar}". *

Custom {@link TypeFilter TypeFilters} may optionally implement any of the * following {@link org.springframework.beans.factory.Aware Aware} interfaces, and * their respective methods will be called prior to {@link TypeFilter#match match}: *

    *
  • {@link org.springframework.context.EnvironmentAware EnvironmentAware}
  • *
  • {@link org.springframework.beans.factory.BeanFactoryAware BeanFactoryAware} *
  • {@link org.springframework.beans.factory.BeanClassLoaderAware BeanClassLoaderAware} *
  • {@link org.springframework.context.ResourceLoaderAware ResourceLoaderAware} *
*

Specifying zero classes is permitted but will have no effect on component * scanning. * @since 4.2 * @see #value * @see #type */ @AliasFor("value") Class<?>[] classes() default {}; /** * The pattern (or patterns) to use for the filter, as an alternative * to specifying a Class {@link #value}. *

If {@link #type} is set to {@link FilterType#ASPECTJ ASPECTJ}, * this is an AspectJ type pattern expression. If {@link #type} is * set to {@link FilterType#REGEX REGEX}, this is a regex pattern * for the fully-qualified class names to match. * @see #type * @see #classes */ String[] pattern() default {}; } }

@ComponentScan扫描策略

(1)通过使用 value,basePackages 属性来指定扫描范围;
(2)自动扫描指定路径下带有 @Controller,@Service,@Repository,@Component 等注解标注的类到Spring容器中;
(3)通过 includeFilters 将扫描路径下没有以上注解的类加入 Spring 容器;
(4)通过 excludeFilters 将扫描路径下的类过滤并标识出无需加入到Spring 容器的类;
(5)通过自定义的方式,将符合规则的类加入到Spring容器中。

如何使用?

在基于SpringBoot框架的项目中,在默认的启动类上会被添加@SpringBootApplication注解,这个注解默认可以帮我们启用 SpringBoot 的自动配置功能。
@SpringBootApplication是一个组合注解,相当于使用一个@SpringBootApplication可以替代@SpringBootConfiguration,@EnableAutoConfiguration,@ComponentScan几个注解联合使用。我们可以通过对@SpringBootApplication的属性scanBasePackages,实现对@ComponentScan中的属性basePackages进行自定义。

源码、示例及DEMO

源码、示例及DEMO

你可能感兴趣的:(SpringBoot,spring,boot)