写在前面
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.
* <p>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.
* <p>The default is defer to the default behavior of the component scanner used to
* execute the actual scan.
* <p>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.
* <p>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.
* <p>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.
* <p>The following table explains how the classes will be interpreted
* based on the configured value of the {@link #type} attribute.
* <table border="1">
* <tr><th>{@code FilterType}</th><th>Class Interpreted As</th></tr>
* <tr><td>{@link FilterType#ANNOTATION ANNOTATION}</td>
* <td>the annotation itself</td></tr>
* <tr><td>{@link FilterType#ASSIGNABLE_TYPE ASSIGNABLE_TYPE}</td>
* <td>the type that detected components should be assignable to</td></tr>
* <tr><td>{@link FilterType#CUSTOM CUSTOM}</td>
* <td>an implementation of {@link TypeFilter}</td></tr>
* </table>
* <p>When multiple classes are specified, <em>OR</em> logic is applied
* — for example, "include types annotated with {@code @Foo} OR {@code @Bar}".
* <p>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}:
* <ul>
* <li>{@link org.springframework.context.EnvironmentAware EnvironmentAware}</li>
* <li>{@link org.springframework.beans.factory.BeanFactoryAware BeanFactoryAware}
* <li>{@link org.springframework.beans.factory.BeanClassLoaderAware BeanClassLoaderAware}
* <li>{@link org.springframework.context.ResourceLoaderAware ResourceLoaderAware}
* </ul>
* <p>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}.
* <p>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