Bootstrap

Spring Boot注解之@ComponentScan用法和实现原理

@ComponentScan的作用

@Component注解及其衍生注解@RestController、@Controller@Service和@Repository都是组件注册注解

@ComponentScan注解主要是从约定的扫描路径中,识别标注了组件注册注解的类,并且把

这些类自动注册到spring IoC容器中,这些类就是我们通常所言的bean。

​ IoC容器是Spring的特色之一,可以使用它管理bean。当然**@Configration注解修饰的类也会被托管给IoC容器**。

举个例子,你在微博上@某某,对方会优先看到这条信息,并给你反馈。同理,在Spring中,你标识

一个@符号,那么Spring就会关照一下,从你这里拿到一个Bean(自动注册)或者给出一个Bean(自动

装配)。

思考:Spring怎么知道哪些Java类应该当作bean 注册到IOC容器中?

解析:使用配置文件或者注解的方式进行标识需要处理的java类,这些被标注的类被Spring识别bean类。

什么是组件扫描路径

注解@ComponentScan 如果不设置value属性,默认扫描路径是启动类   XxxApplication.java 所在目录及其子目录;所以最好还是配置value属性,减少加载时间,提高系统启动速度。

这个项目中的启动类是:SpringbootApplication.java

该启动类所在的目录是:springboot

那么ComponentScan注解的默认扫描范围是:springboot目录及其下面的所有子包。也就是说,即便不

明确标注@ComponentScan,Spring Boot也会自动搜索当前应用主入口目录及其下方子目录。如果其它

包中的bean 不在当前主包路径下面,则应使用@ComponentScan设置value属性,配置扫描路径。如果

定义了错误的扫描路径,那么在使用注解@Autowired自动装配Bean时会出错,报a bean of type that

could not be found错误。

如何配置扫描路径

@ComponentScan注解既可以扫描包,也可以扫描指定的类。我们只需要指定一个需要扫描的径就

可以达到更改扫描路径的目的。

  • 包路径
    通过value属性设置需要扫描的包:
    @ComponentScan({“com.company.user”,“com.company.service”})

  • 类路径
    通过basePackageClasses属性指定需要扫描的类:

    @ComponentScan(basePackageClasses={XxxService.class, YyyService.class})

@Component和@ComponentScan的区别

@Component和@ComponentScan有什么区别?二者用于不同目的,咱们结合学生抢答老师
  
的问题这一场景来解释。全班同学代表扫描路径下的所有类,就像全班所有同学;@Component表示

哪些类可能是bean的候选者,就像哪些同学举手抢答问题一样。@ComponentScan 搜索组件包中

的类,找到所bean的候选者,就像老师试图找出哪些同学举手抢答问题。成功抢到答题机会的同学

就是被@Autowire装配的

bean了。

ComponentScan注解中几个常用的属性。
  1. value属性的值

指定包扫描路径,value属性的值,就是项目中的一个具体路径

String[] value() default {};

value属性的类型是String数组,也就是支持一次指定多个包扫描路径。这个属性上面添加了一个注解,

@AliasFor(“basePackages”),这个注解的意思就是说,value这个属性等价于basePackages属性

  1. basePackages属性

String[] basePackages() default {};

指定包扫描路径,basePackages属性的值,就是项目中的一个具体路径。basePackages属性的类型是String数组,也就是支持

一次指定多个包扫描路径。basePackages属性上面添加了一个注解,@AliasFor(“value”),这个注解的意思就是说basePackages

这个属性等价于value属性。

  1. - basePackagesClasses

扫描具体的类

Class<?>[] basePackagesClasses() default {};。

basePackagesClasses属性的类型是Class数组,也就是说支持同时指定多个扫描类。

  1. nameGenerator

Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator. class;配置

beanName生成器,默认是BeanNameGenerator。一般情况下,我们都是使用默认的beanName生成

器,但是Spring实现了beanName生成器的可配置。

  1. scopeResolver

Class<? extends ScopeMetaDataResolver> scopeResolver() default AnnotationScopeMetaDataResolver.class;

处理检测到的bean的scope范围。什么意思呢?spring的bean是有作用域的,默认是singleton,这个默认值就是在

ScopeMetaData类中指定的:

private String scopeName = “singleton”;

这个属性也是可选配置,默认的处理bean作用域的实现类是AnnotationScopeMetaDataResolver.class。源码比较简单,就是取注

解上获取指定的scope的value值,如果没有配置,就是用默认的singleton。

  1. ScopedProxyMode

是否为检测到的组件生产代理。

ScopedProxyMode scopedProxy() default ScopedProxyMode. DEFAULT;

ScopedProxyMode是一个枚举类,可选值有四个:DEFAULT,NO,INTERFACES,TARGET_CLASS。

  1. resourcePattern

控制符合组件检测条件的类文件,默认是包扫描下的 **/*.class。

String resourcePattern() default “”"**/*.class";

  1. useDefaultFilters()

boolean useDefaultFilters() default true;
是否对含有以下注解的类开启检测,默认是开启的。

  • @Component

  • @Repository

  • @Service

  • @Controller

  1. includeFilters

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

扫描指定的这些类型。可选类型有5种,定义在枚举类FilterType中:

  • 第一种:ANNOTATION

  • 第二种:ASSIGNABLE_TYPE

  • 第三种:ASPECTJ

  • 第四种:REGEX,正则表达式。

  • 第五种:CUSTOM,自定义类型。

  1. excludeFilters


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


排除过滤器扫描的的类。

;