【源码】Spring —— TypeFilter 解读

本文深入解析Spring框架中的TypeFilter接口及其应用,包括AbstractTypeHierarchyTraversingFilter、AssignableTypeFilter和AnnotationTypeFilter的实现原理。通过示例展示了如何基于类和注解进行类型过滤,帮助理解Spring的组件扫描过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

ClassPathBeanDefinitionScanner 类中,其从父类 ClassPathScanningCandidateComponentProvider 获取需要注册的备选 BeanDefinition 时,会使用 includeFiltersexcludeFilters 对扫描路径下的类进行 匹配过滤

	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 中解析的 ClassMetadataAnnotationMetadata 进行匹配

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值