源码
MetadataReaderFactory
MetadataReaderFactory
是用于创建 MetadataReader
实例的工厂接口,支持通过类名或资源读取类的元数据并可实现缓存优化。
类型 | 类/接口名 | 功能描述 | 是否需要加载类 | 访问方式 |
---|---|---|---|---|
抽象接口 | AnnotatedTypeMetadata | 访问某类型(类或方法)的注解信息 | 否 | 抽象,支持字节码读取 |
抽象接口 | AnnotationMetadata | 访问某类的注解信息 | 否 | 抽象,支持字节码读取 |
抽象接口 | ClassMetadata | 访问某类的基本元数据(类名、父类、接口等) | 否 | 抽象,支持字节码读取 |
抽象接口 | MethodMetadata | 访问某方法的注解和方法签名 | 否 | 抽象,支持字节码读取 |
反射实现 | StandardAnnotationMetadata | 基于反射访问类注解元数据 | 是 | Java反射 |
反射实现 | StandardClassMetadata | 基于反射访问类的基本元数据 | 是 | Java反射 |
反射实现 | StandardMethodMetadata | 基于反射访问方法元数据 | 是 | Java反射 |
public interface MetadataReaderFactory {MetadataReader getMetadataReader(String className) throws IOException;MetadataReader getMetadataReader(Resource resource) throws IOException;
}
SimpleMetadataReaderFactory
SimpleMetadataReaderFactory
根据类名或资源路径加载对应的 .class
文件,创建用于读取类元数据的 MetadataReader
实例。
public class SimpleMetadataReaderFactory implements MetadataReaderFactory {private final ResourceLoader resourceLoader;public SimpleMetadataReaderFactory() {this.resourceLoader = new DefaultResourceLoader();}public SimpleMetadataReaderFactory(@Nullable ResourceLoader resourceLoader) {this.resourceLoader = (resourceLoader != null ? resourceLoader : new DefaultResourceLoader());}public SimpleMetadataReaderFactory(@Nullable ClassLoader classLoader) {this.resourceLoader = (classLoader != null ? new DefaultResourceLoader(classLoader) : new DefaultResourceLoader());}public final ResourceLoader getResourceLoader() {return this.resourceLoader;}@Overridepublic MetadataReader getMetadataReader(String className) throws IOException {try {// "classpath:" + ClassUtils.convertClassNameToResourcePath(className) + ".class"String resourcePath = ResourceLoader.CLASSPATH_URL_PREFIX +ClassUtils.convertClassNameToResourcePath(className) + ClassUtils.CLASS_FILE_SUFFIX;Resource resource = this.resourceLoader.getResource(resourcePath);return getMetadataReader(resource);}catch (FileNotFoundException ex) {int lastDotIndex = className.lastIndexOf('.');if (lastDotIndex != -1) {String innerClassName =className.substring(0, lastDotIndex) + '$' + className.substring(lastDotIndex + 1);String innerClassResourcePath = ResourceLoader.CLASSPATH_URL_PREFIX +ClassUtils.convertClassNameToResourcePath(innerClassName) + ClassUtils.CLASS_FILE_SUFFIX;Resource innerClassResource = this.resourceLoader.getResource(innerClassResourcePath);if (innerClassResource.exists()) {return getMetadataReader(innerClassResource);}}throw ex;}}@Overridepublic MetadataReader getMetadataReader(Resource resource) throws IOException {return new SimpleMetadataReader(resource, this.resourceLoader.getClassLoader());}
}
CachingMetadataReaderFactory
CachingMetadataReaderFactory
是 SimpleMetadataReaderFactory
的缓存增强版,针对每个 .class
文件资源缓存对应的 MetadataReader
实例,避免重复解析,提高读取类元数据的效率,并支持缓存大小限制与线程安全访问。
public class CachingMetadataReaderFactory extends SimpleMetadataReaderFactory {public static final int DEFAULT_CACHE_LIMIT = 256;@Nullableprivate Map<Resource, MetadataReader> metadataReaderCache;public CachingMetadataReaderFactory() {super();setCacheLimit(DEFAULT_CACHE_LIMIT);}public CachingMetadataReaderFactory(@Nullable ClassLoader classLoader) {super(classLoader);setCacheLimit(DEFAULT_CACHE_LIMIT);}public CachingMetadataReaderFactory(@Nullable ResourceLoader resourceLoader) {super(resourceLoader);if (resourceLoader instanceof DefaultResourceLoader defaultResourceLoader) {this.metadataReaderCache = defaultResourceLoader.getResourceCache(MetadataReader.class);}else {setCacheLimit(DEFAULT_CACHE_LIMIT);}}public void setCacheLimit(int cacheLimit) {if (cacheLimit <= 0) {this.metadataReaderCache = null;}else if (this.metadataReaderCache instanceof LocalResourceCache localResourceCache) {localResourceCache.setCacheLimit(cacheLimit);}else {this.metadataReaderCache = new LocalResourceCache(cacheLimit);}}public int getCacheLimit() {if (this.metadataReaderCache instanceof LocalResourceCache localResourceCache) {return localResourceCache.getCacheLimit();}else {return (this.metadataReaderCache != null ? Integer.MAX_VALUE : 0);}}@Overridepublic MetadataReader getMetadataReader(Resource resource) throws IOException {if (this.metadataReaderCache instanceof ConcurrentMap) {MetadataReader metadataReader = this.metadataReaderCache.get(resource);if (metadataReader == null) {metadataReader = super.getMetadataReader(resource);this.metadataReaderCache.put(resource, metadataReader);}return metadataReader;}else if (this.metadataReaderCache != null) {synchronized (this.metadataReaderCache) {MetadataReader metadataReader = this.metadataReaderCache.get(resource);if (metadataReader == null) {metadataReader = super.getMetadataReader(resource);this.metadataReaderCache.put(resource, metadataReader);}return metadataReader;}}else {return super.getMetadataReader(resource);}}public void clearCache() {if (this.metadataReaderCache instanceof LocalResourceCache) {synchronized (this.metadataReaderCache) {this.metadataReaderCache.clear();}}else if (this.metadataReaderCache != null) {setCacheLimit(DEFAULT_CACHE_LIMIT);}}@SuppressWarnings("serial")private static class LocalResourceCache extends LinkedHashMap<Resource, MetadataReader> {private volatile int cacheLimit;public LocalResourceCache(int cacheLimit) {super(cacheLimit, 0.75f, true);this.cacheLimit = cacheLimit;}public void setCacheLimit(int cacheLimit) {this.cacheLimit = cacheLimit;}public int getCacheLimit() {return this.cacheLimit;}@Overrideprotected boolean removeEldestEntry(Map.Entry<Resource, MetadataReader> eldest) {return size() > this.cacheLimit;}}
}
MetadataReader
MetadataReader
是一个用于读取类文件元数据(包括类信息和注解信息)的简单门面接口,常用于组件扫描过程中的类型过滤判断。
public interface MetadataReader {Resource getResource();ClassMetadata getClassMetadata();AnnotationMetadata getAnnotationMetadata();
}
SimpleMetadataReader
final class SimpleMetadataReader implements MetadataReader {// 性能优化:不加载无用信息,加快 ClassReader 处理速度。// 避免类初始化:避免加载类体或触发静态初始化,保证扫描阶段安全。// 只关注元数据:如类名、注解、父类、接口、方法签名等,无需方法体逻辑。// 跳过类的调试信息、方法字节码和帧信息,只保留元数据,从而提升类扫描效率。private static final int PARSING_OPTIONS = (ClassReader.SKIP_DEBUG | ClassReader.SKIP_CODE | ClassReader.SKIP_FRAMES);private final Resource resource;private final AnnotationMetadata annotationMetadata;SimpleMetadataReader(Resource resource, @Nullable ClassLoader classLoader) throws IOException {SimpleAnnotationMetadataReadingVisitor visitor = new SimpleAnnotationMetadataReadingVisitor(classLoader);getClassReader(resource).accept(visitor, PARSING_OPTIONS);this.resource = resource;this.annotationMetadata = visitor.getMetadata();}private static ClassReader getClassReader(Resource resource) throws IOException {try (InputStream is = resource.getInputStream()) {try {return new ClassReader(is);}catch (IllegalArgumentException ex) {throw new ClassFormatException("ASM ClassReader failed to parse class file - " +"probably due to a new Java class file version that is not supported yet. " +"Consider compiling with a lower '-target' or upgrade your framework version. " +"Affected class: " + resource, ex);}}}@Overridepublic Resource getResource() {return this.resource;}@Overridepublic ClassMetadata getClassMetadata() {return this.annotationMetadata;}@Overridepublic AnnotationMetadata getAnnotationMetadata() {return this.annotationMetadata;}}
SimpleAnnotationMetadataReadingVisitor
SimpleAnnotationMetadataReadingVisitor
是基于 ASM 的 ClassVisitor实现,用于读取类的注解、方法、父类、接口等元信息,并构建 SimpleAnnotationMetadata。
final class SimpleAnnotationMetadataReadingVisitor extends ClassVisitor {@Nullableprivate final ClassLoader classLoader;// 当前类的全限定名private String className = "";// 类的访问修饰符(如 public, abstract, interface)private int access;// 父类名称(不包括 Object)@Nullableprivate String superClassName;// 若当前类是内部类,记录其外部类名@Nullableprivate String enclosingClassName;// 是否是静态内部类private boolean independentInnerClass;// 实现的接口集合private final Set<String> interfaceNames = new LinkedHashSet<>(4);// 当前类包含的成员类(如内部类)private final Set<String> memberClassNames = new LinkedHashSet<>(4);// 所有类级别的合并注解private final Set<MergedAnnotation<?>> annotations = new LinkedHashSet<>(4);// 所有非构造器、非桥方法的元数据private final Set<MethodMetadata> declaredMethods = new LinkedHashSet<>(4);@Nullableprivate SimpleAnnotationMetadata metadata;@Nullableprivate Source source;SimpleAnnotationMetadataReadingVisitor(@Nullable ClassLoader classLoader) {super(SpringAsmInfo.ASM_VERSION);this.classLoader = classLoader;}@Overridepublic void visit(int version, int access, String name, String signature,@Nullable String supername, String[] interfaces) {this.className = toClassName(name);this.access = access;if (supername != null && !isInterface(access)) {this.superClassName = toClassName(supername);}for (String element : interfaces) {this.interfaceNames.add(toClassName(element));}}@Overridepublic void visitOuterClass(String owner, String name, String desc) {this.enclosingClassName = toClassName(owner);}@Overridepublic void visitInnerClass(String name, @Nullable String outerName, String innerName, int access) {if (outerName != null) {String className = toClassName(name);String outerClassName = toClassName(outerName);if (this.className.equals(className)) {this.enclosingClassName = outerClassName;this.independentInnerClass = ((access & Opcodes.ACC_STATIC) != 0);}else if (this.className.equals(outerClassName)) {this.memberClassNames.add(className);}}}// 当扫描到类上的注解时,visitAnnotation 方法会创建一个 MergedAnnotationReadingVisitor 来读取注解内容,并将其添加到注解集合中。@Override@Nullablepublic AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {return MergedAnnotationReadingVisitor.get(this.classLoader, getSource(),descriptor, visible, this.annotations::add);}// visitMethod 方法跳过构造方法和桥接方法,仅为普通用户方法创建 SimpleMethodMetadataReadingVisitor,用于收集方法注解信息并添加到集合中。@Override@Nullablepublic MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {// Skip bridge methods and constructors - we're only interested in original user methods.if (isBridge(access) || name.equals("<init>")) {return null;}return new SimpleMethodMetadataReadingVisitor(this.classLoader, this.className,access, name, descriptor, this.declaredMethods::add);}// 在类字节码扫描结束时,将收集的类名、访问权限、父类、接口、内部类、方法和注解等信息封装为 SimpleAnnotationMetadata 实例,完成类的注解元数据构建。@Overridepublic void visitEnd() {MergedAnnotations annotations = MergedAnnotations.of(this.annotations);this.metadata = new SimpleAnnotationMetadata(this.className, this.access,this.enclosingClassName, this.superClassName, this.independentInnerClass,this.interfaceNames, this.memberClassNames, this.declaredMethods, annotations);}public SimpleAnnotationMetadata getMetadata() {Assert.state(this.metadata != null, "AnnotationMetadata not initialized");return this.metadata;}private Source getSource() {Source source = this.source;if (source == null) {source = new Source(this.className);this.source = source;}return source;}private String toClassName(String name) {return ClassUtils.convertResourcePathToClassName(name);}private boolean isBridge(int access) {return (access & Opcodes.ACC_BRIDGE) != 0;}private boolean isInterface(int access) {return (access & Opcodes.ACC_INTERFACE) != 0;}/*** {@link MergedAnnotation} source.*/private static final class Source {private final String className;Source(String className) {this.className = className;}}}
SimpleMethodMetadataReadingVisitor
SimpleMethodMetadataReadingVisitor
是基于 ASM 的 MethodVisitor 实现,用于读取方法的访问权限、签名、注解等元数据,并将这些方法信息封装成简化的元数据对象供框架使用。
final class SimpleMethodMetadataReadingVisitor extends MethodVisitor {@Nullableprivate final ClassLoader classLoader;private final String declaringClassName;private final int access;private final String methodName;private final String descriptor;private final List<MergedAnnotation<?>> annotations = new ArrayList<>(4);private final Consumer<SimpleMethodMetadata> consumer;@Nullableprivate Source source;SimpleMethodMetadataReadingVisitor(@Nullable ClassLoader classLoader, String declaringClassName,int access, String methodName, String descriptor, Consumer<SimpleMethodMetadata> consumer) {super(SpringAsmInfo.ASM_VERSION);this.classLoader = classLoader;this.declaringClassName = declaringClassName;this.access = access;this.methodName = methodName;this.descriptor = descriptor;this.consumer = consumer;}@Override@Nullablepublic AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {return MergedAnnotationReadingVisitor.get(this.classLoader, getSource(),descriptor, visible, this.annotations::add);}@Overridepublic void visitEnd() {String returnTypeName = Type.getReturnType(this.descriptor).getClassName();MergedAnnotations annotations = MergedAnnotations.of(this.annotations);SimpleMethodMetadata metadata = new SimpleMethodMetadata(this.methodName, this.access,this.declaringClassName, returnTypeName, getSource(), annotations);this.consumer.accept(metadata);}private Object getSource() {Source source = this.source;if (source == null) {source = new Source(this.declaringClassName, this.methodName, this.descriptor);this.source = source;}return source;}/*** {@link MergedAnnotation} source.*/static final class Source {private final String declaringClassName;private final String methodName;private final String descriptor;@Nullableprivate String toStringValue;Source(String declaringClassName, String methodName, String descriptor) {this.declaringClassName = declaringClassName;this.methodName = methodName;this.descriptor = descriptor;}}}
MergedAnnotationReadingVisitor
MergedAnnotationReadingVisitor
通过 ASM 访问字节码中的注解及其属性,递归解析注解及嵌套注解,最终构建出 Spring 框架通用的 MergedAnnotation
元数据对象,便于框架高效统一地读取和处理注解信息。
class MergedAnnotationReadingVisitor<A extends Annotation> extends AnnotationVisitor {@Nullableprivate final ClassLoader classLoader;@Nullableprivate final Object source;private final Class<A> annotationType;private final Consumer<MergedAnnotation<A>> consumer;// 存储注解的所有属性名和值private final Map<String, Object> attributes = new LinkedHashMap<>(4);public MergedAnnotationReadingVisitor(@Nullable ClassLoader classLoader, @Nullable Object source, Class<A> annotationType, Consumer<MergedAnnotation<A>> consumer) {super(SpringAsmInfo.ASM_VERSION);this.classLoader = classLoader;this.source = source;this.annotationType = annotationType;this.consumer = consumer;}@Overridepublic void visit(String name, Object value) {if (value instanceof Type type) {value = type.getClassName();}this.attributes.put(name, value);}@Overridepublic void visitEnum(String name, String descriptor, String value) {visitEnum(descriptor, value, enumValue -> this.attributes.put(name, enumValue));}@Override@Nullablepublic AnnotationVisitor visitAnnotation(String name, String descriptor) {return visitAnnotation(descriptor, annotation -> this.attributes.put(name, annotation));}@Overridepublic AnnotationVisitor visitArray(String name) {return new ArrayVisitor(value -> this.attributes.put(name, value));}@Overridepublic void visitEnd() {Map<String, Object> compactedAttributes = (this.attributes.isEmpty() ? Collections.emptyMap() : this.attributes);MergedAnnotation<A> annotation = MergedAnnotation.of(this.classLoader, this.source, this.annotationType, compactedAttributes);this.consumer.accept(annotation);}@SuppressWarnings("unchecked")public <E extends Enum<E>> void visitEnum(String descriptor, String value, Consumer<E> consumer) {String className = Type.getType(descriptor).getClassName();Class<E> type = (Class<E>) ClassUtils.resolveClassName(className, this.classLoader);consumer.accept(Enum.valueOf(type, value));}@SuppressWarnings("unchecked")@Nullableprivate <T extends Annotation> AnnotationVisitor visitAnnotation(String descriptor, Consumer<MergedAnnotation<T>> consumer) {String className = Type.getType(descriptor).getClassName();if (AnnotationFilter.PLAIN.matches(className)) {return null;}Class<T> type = (Class<T>) ClassUtils.resolveClassName(className, this.classLoader);return new MergedAnnotationReadingVisitor<>(this.classLoader, this.source, type, consumer);}@SuppressWarnings("unchecked")@Nullablestatic <A extends Annotation> AnnotationVisitor get(@Nullable ClassLoader classLoader,@Nullable Object source, String descriptor, boolean visible,Consumer<MergedAnnotation<A>> consumer) {if (!visible) {return null;}String typeName = Type.getType(descriptor).getClassName();if (AnnotationFilter.PLAIN.matches(typeName)) {return null;}try {Class<A> annotationType = (Class<A>) ClassUtils.forName(typeName, classLoader);return new MergedAnnotationReadingVisitor<>(classLoader, source, annotationType, consumer);}catch (ClassNotFoundException | LinkageError ex) {return null;}}/*** {@link AnnotationVisitor} to deal with array attributes.*/private class ArrayVisitor extends AnnotationVisitor {private final List<Object> elements = new ArrayList<>();private final Consumer<Object[]> consumer;ArrayVisitor(Consumer<Object[]> consumer) {super(SpringAsmInfo.ASM_VERSION);this.consumer = consumer;}@Overridepublic void visit(String name, Object value) {if (value instanceof Type type) {value = type.getClassName();}this.elements.add(value);}@Overridepublic void visitEnum(String name, String descriptor, String value) {MergedAnnotationReadingVisitor.this.visitEnum(descriptor, value, this.elements::add);}@Override@Nullablepublic AnnotationVisitor visitAnnotation(String name, String descriptor) {return MergedAnnotationReadingVisitor.this.visitAnnotation(descriptor, this.elements::add);}@Overridepublic void visitEnd() {Class<?> componentType = getComponentType();Object[] array = (Object[]) Array.newInstance(componentType, this.elements.size());this.consumer.accept(this.elements.toArray(array));}private Class<?> getComponentType() {if (this.elements.isEmpty()) {return Object.class;}Object firstElement = this.elements.get(0);if (firstElement instanceof Enum<?> enumeration) {return enumeration.getDeclaringClass();}return firstElement.getClass();}}
}
TypeFilter
TypeFilter
是一个函数式接口,用于基于类的元数据判断该类是否符合组件扫描条件。
@FunctionalInterface
public interface TypeFilter {boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException;
}
org.springframework.core.type.filter
是 spring core包中用于类路径扫描过程中的类型过滤支持包,提供了多种 TypeFilter 实现,可按注解、父类、正则、AspectJ 表达式等条件筛选类。
类名 | 用途 | 特点 |
---|---|---|
TypeFilter | 过滤接口 | 核心接口,所有过滤器的基础 |
AbstractClassTestingTypeFilter | 抽象类 | 提供 ClassMetadata 访问 |
AbstractTypeHierarchyTraversingFilter | 抽象类 | 支持递归检查父类和接口 |
AnnotationTypeFilter | 注解过滤 | 匹配指定注解,可配置是否继承 |
AssignableTypeFilter | 父类/接口匹配 | 匹配指定类型的子类或实现类 |
RegexPatternTypeFilter | 类名正则 | 使用正则表达式匹配类名 |
AspectJTypeFilter | AspectJ 表达式匹配 | 功能强大,适合复杂匹配需求 |
例子
@Component
public class CustomConfig {@Beanpublic Object customObj() {return new Object();}
}
public class CustomTypeFilter implements TypeFilter {@Overridepublic boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {String className = metadataReader.getClassMetadata().getClassName();// 只对 CustomConfig 类进行打印(可以根据需要改成其他判断)if (className.contains("CustomConfig")) {// 打印类上的所有注解MergedAnnotations classAnnotations = metadataReader.getAnnotationMetadata().getAnnotations();System.out.println("Class Annotations of " + className + ":");classAnnotations.stream().forEach(annotation -> {System.out.println(" - " + annotation.getType().getName());});// 打印方法上的所有注解System.out.println("Method Annotations:");for (MethodMetadata methodMetadata : metadataReader.getAnnotationMetadata().getDeclaredMethods()) {System.out.println(" Method: " + methodMetadata.getMethodName());MergedAnnotations methodAnnotations = methodMetadata.getAnnotations();methodAnnotations.stream().forEach(annotation -> {System.out.println(" - " + annotation.getType().getName());});}}// 根据实际需要返回 true 或 false,这里只是打印,返回 false 不影响扫描return false;}
}
@Configuration
@ComponentScan(excludeFilters = @Filter(type = FilterType.CUSTOM, classes = CustomTypeFilter.class))
public class Application {@Beanpublic CommandLineRunner commandLineRunner(ApplicationContext ctx) {return args -> ctx.getBean(CustomConfig.class);}public static void main(String[] args) {SpringApplication.run(Application.class, args);}
}
Class Annotations of xyz.idoly.demo.config.CustomConfig:- org.springframework.stereotype.Component- org.springframework.stereotype.Indexed
Method Annotations:Method: customObj- org.springframework.context.annotation.Bean