【源码】Spring —— TypeFilter 解读

tech2022-08-01  158

【源码】Spring —— TypeFilter 解读

前言版本TypeFilterAbstractTypeHierarchyTraversingFilterAssignableTypeFilterAnnotationTypeFilter demo总结

前言

在 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 等规则 匹配过滤 目标类型

最新回复(0)