Spring 中的 MetaData 接口 (2)

经常这么使用得到注解里面所有的属性值:
AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(annoMetadata, annType);

public interface AnnotationMetadata extends ClassMetadata, AnnotatedTypeMetadata { //拿到当前类上所有的注解的全类名(注意是全类名) Set<String> getAnnotationTypes(); // 拿到指定的注解类型 //annotationName:注解类型的全类名 Set<String> getMetaAnnotationTypes(String annotationName); // 是否包含指定注解 (annotationName:全类名) boolean hasAnnotation(String annotationName); //这个厉害了,用于判断注解类型自己是否被某个元注解类型所标注 //依赖于AnnotatedElementUtils#hasMetaAnnotationTypes boolean hasMetaAnnotation(String metaAnnotationName); // 类里面只有有一个方法标注有指定注解,就返回true //getDeclaredMethods获得所有方法, AnnotatedElementUtils.isAnnotated是否标注有指定注解 boolean hasAnnotatedMethods(String annotationName); // 返回所有的标注有指定注解的方法元信息。注意返回的是MethodMetadata 原理基本同上 Set<MethodMetadata> getAnnotatedMethods(String annotationName); } MethodMetadata

方法的元数据接口

public interface MethodMetadata extends AnnotatedTypeMetadata { String getMethodName(); // Return the fully-qualified name of the class that declares this method. String getDeclaringClassName(); // Return the fully-qualified name of this method's declared return type. String getReturnTypeName(); boolean isAbstract(); boolean isStatic(); boolean isFinal(); boolean isOverridable(); }

这个接口有两个实现:

StandardMethodMetadata:基于反射的标准实现;

MethodMetadataReadingVisitor:基于ASM的实现的,继承自ASM``的org.springframework.asm.MethodVisitor采用Visitor的方式读取到元数据。

元数据,是框架设计中必须的一个概念,所有的流行框架里都能看到它的影子,包括且不限于Spring、SpringBoot、SpringCloud、MyBatis、Hibernate等。它能模糊掉具体的类型,能让数据输出变得统一,能解决Java抽象解决不了的问题,比如运用得最广的便是注解,因为它不能继承无法抽象,所以用元数据方式就可以完美行成统一的向上抽取让它变得与类型无关,也就是常说的模糊效果,这便是框架的核心设计思想。

不管是ClassMetadata还是AnnotatedTypeMetadata都会有基于反射和基于ASM的两种解决方案,他们能使用于不同的场景:

标准反射:它依赖于Class,优点是实现简单,缺点是使用时必须把Class加载进来

ASM:无需提前加载Class入JVM,所有特别特别适用于形如Spring应用扫描的场景(扫描所有资源,但并不是加载所有进JVM/容器~)

MetadataReader

spring 对MetadataReader的描述为:Simple facade for accessing class metadata,as read by an ASM.大意是通过ASM读取class IO流资源组装访问元数据的门面接口

类关系图

img

MetadataReader接口方法 public interface MetadataReader { /** * 返回class文件的IO资源引用 */ Resource getResource(); /** * 为基础class读取基本类元数据,返回基础类的元数据。 */ ClassMetadata getClassMetadata(); /** *为基础类读取完整的注释元数据,包括注释方法的元数据。返回基础类的完整注释元数据 */ AnnotationMetadata getAnnotationMetadata(); }

MetadataReader接口提供三个方法:

返回class文件的IO资源引用

返回基础类的元数据

返回基础类的完整注释元数据

SimpleMetadataReader final class SimpleMetadataReader implements MetadataReader { //class类IO流资源引用 private final Resource resource; //class类元数据 private final ClassMetadata classMetadata; //class类完整注释元数据 private final AnnotationMetadata annotationMetadata; /** * 构建函数,用于通过过ASM字节码操控框架读取class读取class资源流 */ SimpleMetadataReader(Resource resource, @Nullable ClassLoader classLoader) throws IOException { // 获取class类IO流 InputStream is = new BufferedInputStream(resource.getInputStream()); ClassReader classReader; try { //通过ASM字节码操控框架读取class classReader = new ClassReader(is); } catch (IllegalArgumentException ex) { } finally { is.close(); } //注解元数据读取访问者读取注解元数据 AnnotationMetadataReadingVisitor visitor = new AnnotationMetadataReadingVisitor(classLoader); classReader.accept(visitor,ClassReader.SKIP_DEBUG); //注解元数据 this.annotationMetadata = visitor; //class元数据 this.classMetadata = visitor; this.resource = resource; } @Override public Resource getResource() { return this.resource; } @Override public ClassMetadata getClassMetadata() { //返回当前类元数据 return this.classMetadata; } @Override public AnnotationMetadata getAnnotationMetadata() { //返回当前类的注解元数据 return this.annotationMetadata; } }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wssdys.html