1. 基本使用
1.1 指定包路径
@ComponentScan
这个注解大家再 Spring/SpringBoot 中应该都非常常见,我们常常会一定一些包路径去进行扫描,从而加载我们想要注入的一些 Bean。
例如我先创建了一些 Bean,然后写了一个配置类
- 这个 Bean 没任何特殊的内容,在不同创建空的 Bean 加上 @Component 注解即可,大家可以多试几个类型,例如接口,普通类等等。
- @ComponentScan 注解通过默认的属性 value 可以指定一个包路径,通过 basePackages 能指定多个。
测试(下面都用这个,就不再冗余的去贴了)@Configuration
@ComponentScan(value = "com.ideal.scan")
public class PackageConfiguration {
}
运行结果,可以看到我们在 com.ideal.scan 这个包下的 beanpublic 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); } }
都打印出来了。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. 过滤
除了基本使用,它还支持对包扫描进行指定条件的过滤。
其中 TestAnno 是我随便创的一个注解,然后我把他加在 Student 这个类上,这样它就能加载出含有这个注解的 Bean,但是大家要注意,前面指定的 basePackages 也一样会生效,而且如果大家不设置@Configuration @ComponentScan(basePackages = "com.ideal.scan", includeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, value = TestAnno.class), useDefaultFilters = false) public class PackageConfiguration { }
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