开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第29天,点击查看活动详情
@ComponentScan包路径扫描
我们通常使用@ComponentScan注解来进行组件扫描,具体有两种方式:
- 借用它的value属性(放入待扫描的包路径)
- 借用它的basePackages属性(放入要扫描的类的字节码,如A.class)
对于选用basePackages(A.class)方式进行的扫描,它会扫描到A所在的包。
假设A、B都在Bean包下,C不在Bean包。我们借用basePackages属性来扫描:
@Configuration
@ComponentScan(basePackageClasses =A.class)
public class Configuration {
}
之后写一个启动类如下:
public class Application {
public static void main(String[] args) throws Exception {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Configuration.class);
String[] beanDefinitionNames = ctx.getBeanDefinitionNames();
Stream.of(beanDefinitionNames).forEach(System.out::println);
}
}
运行完会发现只打印了A、B,没有打印C。
扫描过滤
实际开发中,扫描到的路径,我们不一定都想要,那这个时候就需要过滤一下。当然还是需要用@ComponentScan注解,这里主要讲几个属性。
includeFilters按注解包含
我们首先扫描spring包下的所有组件,然后使用includeFilters属性把所有带Animal注解的类也扫描进来,这样就会扫描spring包下所有带@Component注解的(默认规则)和所有带@Animal注解的类了。
@ComponentScan(basePackages = "com.lyz.spring",
includeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, value = Animal.class))
excludeFilters按注解排除
使用方法和includeFilters一样如下,它会排除所有带@Animal注解的
@ComponentScan(basePackages = "com.lyz.spring",
includeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, value = Animal.class))
当然,也不只是可以按注解来过滤,也可按类型来过滤。将@ComponentScan.Filter里的FilterType.ANNOTATION属性改成type = FilterType.ASSIGNABLE_TYPE即可。
自定义过滤
使用自定义过滤需要实现TypeFilter接口,该接口只有一个match方法:
boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException;
metadataReader可以读取到正在扫描到类,用getClassMetadata拿到基本信息;metadataReaderFactory借助 ReaderFactory 可以获取到 Reader ,借助 Reader 可以获取到指定类的信息。
MetadataReader 中有一个 getClassMetadata 方法,可以拿到正在扫描的类的基本信息,咱可以由此取到全限定类名,进而与咱需求中的 Green 类做匹配:
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
throws IOException {
ClassMetadata classMetadata = metadataReader.getClassMetadata();
return classMetadata.getClassName().equals(A.class.getName());
}
下一步在配置类的@CompontScan注解下写 @ComponentScan.Filter(type = FilterType.CUSTOM, value = AFilter.class)来使用自定义注解添加过滤声明。
除了以上三种方法,还有两种方法:使用正则表达式过滤、使用切点表达式过滤。个人认为上述三种方法使用较多。