【源码】Spring —— TypeFilter 解读
前言
在 ClassPathBeanDefinitionScanner 类中,其从父类 ClassPathScanningCandidateComponentProvider 获取需要注册的备选 BeanDefinition 时,会使用 includeFilters
和 excludeFilters
对扫描路径下的类进行 匹配过滤
private final List<TypeFilter> includeFilters = new LinkedList<>();
private final List<TypeFilter> excludeFilters = new LinkedList<>();
本章节介绍 TypeFilter
版本
Spring 5.2.x
TypeFilter
@FunctionalInterface
public interface TypeFilter {
boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
throws IOException;
}
函数式接口,不难推测应该是以 MetadataReader 中解析的 ClassMetadata 和 AnnotationMetadata 进行匹配
关于 ClassMetadata 和 AnnotationMetadata,可以阅读下面文章
【源码】Spring —— ClassMetadata AnnotatedTypeMetadata 解读
AbstractTypeHierarchyTraversingFilter
public abstract class AbstractTypeHierarchyTraversingFilter implements TypeFilter {
protected final Log logger = LogFactory.getLog(getClass());
// 是否考虑父类匹配
private final boolean considerInherited;
// 是否考虑接口匹配
private final boolean considerInterfaces;
protected AbstractTypeHierarchyTraversingFilter(boolean considerInherited, boolean considerInterfaces) {
this.considerInherited = considerInherited;
this.considerInterfaces = considerInterfaces;
}
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
throws IOException {
// 提供了一个快速匹配的通道,可由子类复写
if (matchSelf(metadataReader)) {
return true;
}
// 类匹配,子类复写
ClassMetadata metadata = metadataReader.getClassMetadata();
if (matchClassName(metadata.getClassName())) {
return true;
}
// 如果考虑父类匹配
if (this.considerInherited) {
String superClassName = metadata.getSuperClassName();
if (superClassName != null) {
Boolean superClassMatch = matchSuperClass(superClassName);
if (superClassMatch != null) {
if (superClassMatch.booleanValue()) {
return true;
}
}
else {
try {
// 递归匹配父类
if (match(metadata.getSuperClassName(), metadataReaderFactory)) {
return true;
}
}
catch (IOException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Could not read super class [" + metadata.getSuperClassName() +
"] of type-filtered class [" + metadata.getClassName() + "]");
}
}
}
}
}
// 接口匹配
if (this.considerInterfaces) {
for (String ifc : metadata.getInterfaceNames()) {
Boolean interfaceMatch = matchInterface(ifc);
if (interfaceMatch != null) {
if (interfaceMatch.booleanValue()) {
return true;
}
}
else {
try {
if (match(ifc, metadataReaderFactory)) {
return true;
}
}
catch (IOException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Could not read interface [" + ifc + "] for type-filtered class [" +
metadata.getClassName() + "]");
}
}
}
}
}
return false;
}
// 略
}
AbstractTypeHierarchyTraversingFilter,抽象方法,定义了 match
方法的模板,具体实现都交给子类实现
AssignableTypeFilter
public class AssignableTypeFilter extends AbstractTypeHierarchyTraversingFilter {
// 指定 class 类型
private final Class<?> targetType;
public AssignableTypeFilter(Class<?> targetType) {
// 考虑 父类 和 接口
super(true, true);
this.targetType = targetType;
}
public final Class<?> getTargetType() {
return this.targetType;
}
// 类名匹配
@Override
protected boolean matchClassName(String className) {
return this.targetType.getName().equals(className);
}
@Override
@Nullable
protected Boolean matchSuperClass(String superClassName) {
return matchTargetType(superClassName);
}
@Override
@Nullable
protected Boolean matchInterface(String interfaceName) {
return matchTargetType(interfaceName);
}
// 父类匹配、接口匹配
@Nullable
protected Boolean matchTargetType(String typeName) {
// 类名相同匹配成功
if (this.targetType.getName().equals(typeName)) {
return true;
}
// 目标类是 Object 则匹配失败,其实就相当于其下所有子类都已经匹配失败了
else if (Object.class.getName().equals(typeName)) {
return false;
}
// 如果给定类名以 java 打头,则加载该类,并判断是否 targetType 的子类
else if (typeName.startsWith("java")) {
try {
Class<?> clazz = ClassUtils.forName(typeName, getClass().getClassLoader());
return this.targetType.isAssignableFrom(clazz);
}
catch (Throwable ex) {
}
}
return null;
}
}
基于 Class 类型的匹配,考虑 父类 和 接口,实现了抽象父类定义的匹配方法,匹配细节见注释
AnnotationTypeFilter
public class AnnotationTypeFilter extends AbstractTypeHierarchyTraversingFilter {
// 指定 Annotation 类型
private final Class<? extends Annotation> annotationType;
// 是否考虑元注解,默认考虑
private final boolean considerMetaAnnotations;
public AnnotationTypeFilter(Class<? extends Annotation> annotationType) {
this(annotationType, true, false);
}
public AnnotationTypeFilter(Class<? extends Annotation> annotationType, boolean considerMetaAnnotations) {
this(annotationType, considerMetaAnnotations, false);
}
public AnnotationTypeFilter(
Class<? extends Annotation> annotationType, boolean considerMetaAnnotations, boolean considerInterfaces) {
// 是否考虑父类取决于给定注解是否标注 Inherited
super(annotationType.isAnnotationPresent(Inherited.class), considerInterfaces);
this.annotationType = annotationType;
this.considerMetaAnnotations = considerMetaAnnotations;
}
public final Class<? extends Annotation> getAnnotationType() {
return this.annotationType;
}
@Override
protected boolean matchSelf(MetadataReader metadataReader) {
AnnotationMetadata metadata = metadataReader.getAnnotationMetadata();
// 标注有注定注解 或者 被注定元注解标注(前提是 considerMetaAnnotations = true)
return metadata.hasAnnotation(this.annotationType.getName()) ||
(this.considerMetaAnnotations && metadata.hasMetaAnnotation(this.annotationType.getName()));
}
@Override
@Nullable
protected Boolean matchSuperClass(String superClassName) {
return hasAnnotation(superClassName);
}
@Override
@Nullable
protected Boolean matchInterface(String interfaceName) {
return hasAnnotation(interfaceName);
}
@Nullable
protected Boolean hasAnnotation(String typeName) {
// 目标类是 Object 则不匹配,相当于子类都没匹配
if (Object.class.getName().equals(typeName)) {
return false;
}
// 目标类以 java 开头
else if (typeName.startsWith("java")) {
// annotationType 不以 java 开头则不匹配
if (!this.annotationType.getName().startsWith("java")) {
// Standard Java types do not have non-standard annotations on them ->
// skip any load attempt, in particular for Java language interfaces.
return false;
}
try {
/**
* 加载目标类
* 根据是否考虑元注解进行匹配
*/
Class<?> clazz = ClassUtils.forName(typeName, getClass().getClassLoader());
return ((this.considerMetaAnnotations ? AnnotationUtils.getAnnotation(clazz, this.annotationType) :
clazz.getAnnotation(this.annotationType)) != null);
}
catch (Throwable ex) {
}
}
return null;
}
}
基于 Annotation 类型的匹配,匹配细节见注释
demo
public void test() throws IOException {
// 基于 class
TypeFilter classTypeFilter =
new AssignableTypeFilter(A.class);
// 基于 Annotation
TypeFilter annotationTypeFilter =
new AnnotationTypeFilter(Component.class);
MetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory();
MetadataReader metadataReader = metadataReaderFactory.getMetadataReader("com.xsn.convert.TestTypeFilter.B");
System.out.println(classTypeFilter.match(metadataReader, metadataReaderFactory));
System.out.println(annotationTypeFilter.match(metadataReader, metadataReaderFactory));
}
结果:
true
true
总结
很简单的一个类,主要基于 Class Annotation 等规则 匹配过滤 目标类型