TypeFilter, 望名思义,根据类型进行过滤。它是一个接口,有且只有一个match方法需要实现。
@FunctionalInterface
public interface TypeFilter {
boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException;
}
它一般使用在哪些场合呢?
? ? ? ? 答:可能有很多场合,但我目前只知道一个,那就是用于Bean的自动扫描加载。
它又如何使用呢?
? ? ? ? 答:有一个注解会使用它,那就是@ComponentScan注解,它有一个属性:includeFilters;需要指定类型为Filter的参数。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {
@AliasFor("basePackages")
String[] value() default {};
@AliasFor("value")
String[] basePackages() default {};
Class<?>[] basePackageClasses() default {};
Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;
ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;
String resourcePattern() default ClassPathScanningCandidateComponentProvider.DEFAULT_RESOURCE_PATTERN;
boolean useDefaultFilters() default true;
Filter[] includeFilters() default {};
Filter[] excludeFilters() default {};
boolean lazyInit() default false;
@Retention(RetentionPolicy.RUNTIME)
@Target({})
@interface Filter {
FilterType type() default FilterType.ANNOTATION;
@AliasFor("classes")
Class<?>[] value() default {};
@AliasFor("value")
Class<?>[] classes() default {};
String[] pattern() default {};
}
}
下来,给大家一个示例:
import org.springframework.core.io.Resource;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;
import java.io.IOException;
public class MyTypeFilter implements TypeFilter {
/**
*
* @param metadataReader 读取到的当前正在扫描的类的信息
* @param metadataReaderFactory 可以获取到其他任何类信息
* @return
* @throws IOException
*/
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
//获取当前类注解的信息
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
//获取当前正在扫描的类的类信息
ClassMetadata classMetadata = metadataReader.getClassMetadata();
//获取当前类资源(类的路径)
Resource resource = metadataReader.getResource();
String className = classMetadata.getClassName();
System.out.println("---: " + className);
//类名包含Service的类都会被装载为Bean
if (className.contains("Service")){
return true;
}
return false;
}
}
这个配置类指定了扫描的根目录(value="xxx"字段),并且,过滤方式是MyTypeFilter类(classes =xxx),也就是我们自定义的类。
使用默认过滤器为true,也就是使用@Component, @Service,? @Controller注解的类也会被注册到实例中。
@ComponentScan(value = "com.cosseen.bean", includeFilters = {
@ComponentScan.Filter(type = FilterType.CUSTOM, classes = MyTypeFilter.class)
}, useDefaultFilters = true)
public class MyFilterConfig {
}
public class AppFilter {
public static void main(String[] args){
ApplicationContext ctx = new AnnotationConfigApplicationContext(MyFilterConfig.class);
String[] names = ctx.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name);
}
}
}
在com.cosseen.bean目录下的类名包含Service的类,会被自动装载到上下文中。使用传统注解的组件也会自动装载到上下文中。