• 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属性,减少加载时间,提高系统启动速度。

      比如启动类在包 com.eg.wiener 下面,那么项目启动时,会默认扫描wiener包及其子包下的所有类。也就是说,即便不明确标注@ComponentScan,Spring Boot也会自动搜索当前应用主入口目录及其下方子目录。如果其它包中的bean 不在当前主包路径下面,则应使用@ComponentScan设置value属性,配置扫描路径。如果定义了错误的扫描路径,那么在使用注解@Autowired自动装配Bean时会出错,报a bean of type that could not be found错误。

    配置扫描路径

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

    1. 包路径

      通过value属性设置需要扫描的包:

    @ComponentScan({"com.company.user","com.company.service"})

    1. 类路径

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

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

    @Component和@ComponentScan的区别

      @Component和@ComponentScan有什么区别?二者用于不同目的,咱们结合学生抢答老师的问题这一场景来解释。@Component表示哪些类可能是bean的候选者,就像哪些同学举手抢答问题一样。@ComponentScan 搜索组件包中的类,找到所有bean的候选者,就像老师试图找出哪些同学举手抢答问题。通俗一点解释,就是全班同学代表扫描路径下的所有类,抢答者就是被@Component注解修饰的类,而找到所有抢答者的老师就是@ComponentScan。延伸一点,成功抢到答题机会的同学就是被@Autowire装配的bean了。

    注解@ComponentScan实现原理

      本节介绍 Spring Boot 中注解 @ComponentScan 的实现原理。

      下面介绍一下ComponentScan注解中几个常用的属性。

    1. String[] value() default {};
      指定包扫描路径,value属性的值,就是项目中的一个具体路径。value属性的类型是String数组,也就是支持一次指定多个包扫描路径。这个属性上面添加了一个注解,@AliasFor("basePackages"),这个注解的意思就是说,value这个属性等价于basePackages属性。关于basePackages属性,下面会讲到。
    2. Class<?>[] basePackagesClasses() default {};
      扫描具体的类。basePackagesClasses属性的类型是Class数组,也就是说支持同时指定多个扫描类。
    3. Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator. class;
      配置beanName生成器,默认是BeanNameGenerator。一般情况下,我们都是使用默认的beanName生成器,但是Spring实现了beanName生成器的可配置。
    4. boolean useDefaultFilters() default true;
      是否对含有以下注解的类开启检测,默认是开启的。
      @Component
      @Repository
      @Service
      @Controller
    5. ComponentScan.Filter[] includeFilters() default {};
      指定某些Filter扫描到的类。听起来有些费劲,说白了就是指定了类型,扫描指定的这些类型。可选类型有5种,定义在枚举类FilterType中:
      第一种:ANNOTATION
      第二种:ASSIGNABLE_TYPE
      第三种:ASPECTJ
      第四种:REGEX,正则表达式。
      第五种:CUSTOM,自定义类型。
    6. ComponentScan.Filter[] excludeFilters() default {};
      排除过滤器扫描的的类。

    Reference


      读后有收获,小礼物走一走,请作者喝咖啡。

    赞赏支持

  • 相关阅读:
    nullnull聚类小文(二)
    classjavaCore Java Question List #6
    设置仿真器HJTAG ARM仿真器和MDK 联调设置
    二分图判断hdu 1829 A Bug's Life
    信息掩码游戏地图掩码相关(msk)
    导航accessibilityAndroid 抽屉导航
    算法nodehdu 2112 hdu today
    链接函数hdu 1234开门人和关门人
    分配器内存一步一步写STL:空间配置器(1)
    程序连接如何使用JLink V8 烧写程序到NOR Flash
  • 原文地址:https://www.cnblogs.com/east7/p/14390877.html
Copyright © 2020-2023  润新知