这一块主要讲解一下关于扫描相关的内容

1. 基本使用

1.1 指定包路径

@ComponentScan 这个注解大家再 Spring/SpringBoot 中应该都非常常见,我们常常会一定一些包路径去进行扫描,从而加载我们想要注入的一些 Bean。

例如我先创建了一些 Bean,然后写了一个配置类

  • 这个 Bean 没任何特殊的内容,在不同创建空的 Bean 加上 @Component 注解即可,大家可以多试几个类型,例如接口,普通类等等。
  • @ComponentScan 注解通过默认的属性 value 可以指定一个包路径,通过 basePackages 能指定多个。
    1. @Configuration
    2. @ComponentScan(value = "com.ideal.scan")
    3. public class PackageConfiguration {
    4. }
    测试(下面都用这个,就不再冗余的去贴了)
    public class TestScan {
      public static void main(String[] args) {
          AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(PackageConfiguration.class);
          String[] beanDefinitionNames = context.getBeanDefinitionNames();
          Stream.of(beanDefinitionNames).forEach(System.out::println);
      }
    }
    
    运行结果,可以看到我们在 com.ideal.scan 这个包下的 bean
    都打印出来了。
    org.springframework.context.annotation.internalConfigurationAnnotationProcessor
    org.springframework.context.annotation.internalAutowiredAnnotationProcessor
    org.springframework.context.annotation.internalCommonAnnotationProcessor
    org.springframework.context.event.internalEventListenerProcessor
    org.springframework.context.event.internalEventListenerFactory
    packageConfiguration
    testServiceImpl
    student
    teacher
    

    1.2 指定类

    同时它还支持通过指定 bean 加载,例如通过 basePackageClasses = {xxx.class, yyy.class} 这样的方式。或者 @ComponentScan(basePackageClasses = TestService.class)�

    2. 过滤

    除了基本使用,它还支持对包扫描进行指定条件的过滤。
    @Configuration
    @ComponentScan(basePackages = "com.ideal.scan",
                 includeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, value = TestAnno.class),
                 useDefaultFilters = false)
    public class PackageConfiguration {
    }
    
    其中 TestAnno 是我随便创的一个注解,然后我把他加在 Student 这个类上,这样它就能加载出含有这个注解的 Bean,但是大家要注意,前面指定的 basePackages 也一样会生效,而且如果大家不设置 useDefaultFilters = false Spring 默认也会执行其默认的规则,即加载加了 @Component 、@Repository 、@Service 或 @Controller 注解的 Bean,所以设为 false 才能取消这个默认规则,使用自己的规则。 ```java @Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface TestAnno {

}

对应 include 的就是 exclude,大家可以自己试试,就是反向的,查找不包括的。

**@Filter 中的 FilterType**

- ANNOTATION:注解类型
- ASSIGNABLE_TYPE:ANNOTATION:指定的类型
- ASPECTJ:按照Aspectj的表达式,基本上不会用到
- REGEX:按照正则表达式
- CUSTOM:自定义规则

自定义怎么用呢?实现 TypeFilter 即可
```java
@FunctionalInterface
public interface TypeFilter {
    boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException;
}
  • metadataReader :the metadata reader for the target class
    • 这个 Reader 可以读取到正在扫描的类的信息(包括类的信息、类上标注的注解等)
  • metadataReaderFactory :a factory for obtaining metadata readers for other classes (such as superclasses and interfaces)
    • 这个 Factory 可以获取到其他类的 Reader ,进而获取到那些类的信息

比如这样

public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
         throws IOException {
    ClassMetadata classMetadata = metadataReader.getClassMetadata();
    return classMetadata.getClassName().equals(Test.class.getName());
}

其他类型就不一一举例了,认识就好。想用的时候可以查一个 Demo