@ComponentScan注解,扫描哪些包下,将扫描到的包下的组件加入到容器中,这是一个常见的用法,如@ComponentScan(value = "me.xf"),对扫描到的包下的组件,处理哪些组件可以加入到容器中,哪些组件类型的,不可以加入到容器中,这里引入了两个ComponentScan的参数:excludeFilters和includeFilters。
excludeFilters,在扫描到的包下,把哪些给排除掉。excludeFilters 是一个 ComponentScan.Filter[],Filter也是一个注解,接收的参数为要过滤的类型,要过滤的类类型。在Filter中,默认是过滤注解类型,可以改变FilterType的值,来更改过滤的类型,
@Retention(RetentionPolicy.RUNTIME)
@Target({})
public @interface Filter {
FilterType type() default FilterType.ANNOTATION;
@AliasFor("classes")
Class<?>[] value() default {};
@AliasFor("value")
Class<?>[] classes() default {};
String[] pattern() default {};
}
FilterType有以下几个值:
public enum FilterType {
ANNOTATION,
ASSIGNABLE_TYPE,
ASPECTJ,
REGEX,
CUSTOM;
private FilterType() {
}
}
分别是按照注解类型、按照给定的类型、按照Aspectj类型、按照正则表达式以及自定义类型,常用的就是按照注解类型和自定义类型来进行过滤。
使用自定义类型过滤,创建一个类,实现TypeFilter接口,复写match方法,在match方法中,可以拿到类的信息,从而定制自己的过滤规则:
public class MyTypeFilter implements TypeFilter {
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
//获得当前正在扫描的类的注解信息
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
//获得当前正在扫描的类的资源信息
Resource resource = metadataReader.getResource();
//获得当前正在扫描的类的类信息
ClassMetadata classMetadata = metadataReader.getClassMetadata();
String name = classMetadata.getClassName();
System.out.println("扫描的类-->" + name);
if(name.contains("Service")){
System.out.println("匹配成功的类-->" + name);
return true;
}
return false;
}
}
includeFilters和excludeFilters类似,只是作用和其相反,是将哪些组件给加入进来,区别在于,要多添加一个 useDefaultFilters = false 的参数。
在配置类中,填写好相应的参数即可使其生效
//配置类
@Configuration
@ComponentScan(value = "me.xf" , //扫描哪些包下的组件
// excludeFilters = { //在扫描的包下,排除哪些
// @ComponentScan.Filter(type = FilterType.ANNOTATION , //过滤类型,注解类型
// classes = { //确定过滤的类
// Repository.class
// }
// )
// },
// includeFilters = { //在扫描的包下,包含哪些
// @ComponentScan.Filter(type = FilterType.ANNOTATION, //过滤类型
// classes = { //确定过滤的类
// Controller.class
// }
// )
// }
includeFilters = {
@ComponentScan.Filter(type = FilterType.CUSTOM, //过滤类型,自定义类型
classes = { //自定义的类,该类实现TypeFilter接口,复写match方法,在方法中定义过滤的规则
MyTypeFilter.class
}
)
}
,useDefaultFilters = false //使用includeFilters时,要将useDefaultFilters设置为false
)
public class MyConfig {
static {
System.out.println("配置类加载...");
}
@Bean("person") //默认为方法名小写,返回的bean的id
public Person getPerson(){
System.out.println("向容器中添加person");
return new Person("张三",20);
}
}
//测试类
public class AnnotationTest {
@Test
public void testComponentScan(){
System.out.println("======测试类开始======");
ApplicationContext ctx = new AnnotationConfigApplicationContext(MyConfig.class);
System.out.println("======IOC容器创建完成======");
String[] definitionNames = ctx.getBeanDefinitionNames();
for (String name : definitionNames){
System.out.println("bean 的定义名是:" + name);
}
}
}
测试输出: