元数据:数据的数据 比如Class就是一种元数据
Metadata
在org.springframework.core.type
包名下,该包内类不多,主要有以下相关接口和类:
所以我们看到顶层接口有两个:ClassMetadata
和AnnotatedTypeMetadata
ClassMetadata
和AnnotatedTypeMetadata
ClassMetadata
:对Class的封装适配使用它时,并不要求该Bean已经被加载~
它的所有方法,基本上都跟Class有关。
// underlying class:基础的class
public interface ClassMetadata {
// 返回类名(注意返回的是最原始的那个className)
String getClassName();
boolean isInterface();
// 是否是注解
boolean isAnnotation();
boolean isAbstract();
// 是否允许创建 不是接口且不是抽象类 这里就返回true了
boolean isConcrete();
boolean isFinal();
// 是否是独立的(能够创建对象的) 比如是Class、或者内部类、静态内部类
boolean isIndependent();
// 是否有内部类之类的东东
boolean hasEnclosingClass();
@Nullable
String getEnclosingClassName();
boolean hasSuperClass();
@Nullable
String getSuperClassName();
// 会把实现的所有接口名称都返回 具体依赖于Class#getSuperclass
String[] getInterfaceNames();
// 基于:Class#getDeclaredClasses 返回类中定义的公共、私有、保护的内部类
String[] getMemberClassNames();
}
现在看看基本实现:StandardClassMetadata
StandardClassMetadata
public class StandardClassMetadata implements ClassMetadata {
private final Class<?> introspectedClass;
// 就一个构造函数,传进来的Class,作为内部的内省对象
public StandardClassMetadata(Class<?> introspectedClass) {
Assert.notNull(introspectedClass, "Class must not be null");
this.introspectedClass = introspectedClass;
}
... 后面所有的方法实现,都是基于introspectedClass,举例如下:
/**
* Return the underlying Class.
*/
public final Class<?> getIntrospectedClass() {
return this.introspectedClass;
}
@Override
public boolean isInterface() {
return this.introspectedClass.isInterface();
}
@Override
public String[] getMemberClassNames() {
LinkedHashSet<String> memberClassNames = new LinkedHashSet<>(4);
for (Class<?> nestedClass : this.introspectedClass.getDeclaredClasses()) {
memberClassNames.add(nestedClass.getName());
}
return StringUtils.toStringArray(memberClassNames);
}
}
AnnotatedTypeMetadata
:对AnnotatedElement
的封装适配它没有Standard
的实现(毕竟AnnotatedElement
也是接口,没办法做基础实现的),但是它有两个非常重要的子接口:AnnotationMetadata
和MethodMetadata
这两个接口是Spring内部的直接运用
AnnotationMetadata
和MethodMetadata
这两个元数据接口,在Spring内部非常常用,需要掌握。前者Spring2.5就有了,后者Spring3.0才有的
AnnotationMetadata
:对Class相关的多个注解进行获取和判断public interface AnnotationMetadata extends ClassMetadata, AnnotatedTypeMetadata {
//拿到Class上标注的所有注解,依赖于Class#getAnnotations
Set<String> getAnnotationTypes();
// 拿到所有的元注解信息AnnotatedElementUtils#getMetaAnnotationTypes
//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 原理基本同上
// .getDeclaredMethods和AnnotatedElementUtils.isAnnotated 最后吧Method转为MethodMetadata
Set<MethodMetadata> getAnnotatedMethods(String annotationName);
}
MethodMetadata
:方法的元数据
// 基本上是代理了Method introspectedMethod;
public interface MethodMetadata extends AnnotatedTypeMetadata {
// 方法名称
String getMethodName();
// 此方法所属类的全类名
String getDeclaringClassName();
// 方法返回值的全类名
String getReturnTypeName();
// 是否是抽象方法
boolean isAbstract();
// 是否是静态方法
boolean isStatic();
//是否是final方法
boolean isFinal();
// 是否可以被复写(不是静态、不是final、不是private的 就表示可以被复写)
boolean isOverridable();
}
主要实现类有:StandardAnnotationMetadata
、StandardMethodMetadata
、AnnotationMetadataReadingVisitor
、MethodMetadataReadingVisitor
。先聊聊标准实现(前两个)
StandardAnnotationMetadata
:扩展了StandardClassMetadata增加对注解的支持它继承了StandardClassMetadata
,然后实现了AnnotationMetadata
来提供对注解的主持扩展。
public class StandardAnnotationMetadata extends StandardClassMetadata implements AnnotationMetadata {
// 持有对本类所有注解的引用
private final Annotation[] annotations;
private final boolean nestedAnnotationsAsMap;
public StandardAnnotationMetadata(Class<?> introspectedClass, boolean nestedAnnotationsAsMap) {
super(introspectedClass);
this.annotations = introspectedClass.getAnnotations();
this.nestedAnnotationsAsMap = nestedAnnotationsAsMap;
}
...// 它实现了所有AnnotationMetadata 接口的方法 因为实现很简单 此处就省略掉了
}
StandardMethodMetadata
:只实现了MethodMetadata,属于标准实现需要注意的是,它还得实现AnnotatedTypeMetadata
这个接口里的所有方法
public class StandardMethodMetadata implements MethodMetadata {
// 持有方法的引用:内省方法
private final Method introspectedMethod;
private final boolean nestedAnnotationsAsMap;
public StandardMethodMetadata(Method introspectedMethod, boolean nestedAnnotationsAsMap) {
Assert.notNull(introspectedMethod, "Method must not be null");
this.introspectedMethod = introspectedMethod;
this.nestedAnnotationsAsMap = nestedAnnotationsAsMap;
}
... // 实现都非常简单,此处省略 说说AnnotatedTypeMetadata接口的实现
@Override
public boolean isAnnotated(String annotationName) {
return AnnotatedElementUtils.isAnnotated(this.introspectedMethod, annotationName);
}
@Override
@Nullable
public Map<String, Object> getAnnotationAttributes(String annotationName) {
return getAnnotationAttributes(annotationName, false);
}
@Override
@Nullable
public Map<String, Object> getAnnotationAttributes(String annotationName, boolean classValuesAsString) {
return AnnotatedElementUtils.getMergedAnnotationAttributes(this.introspectedMethod,
annotationName, classValuesAsString, this.nestedAnnotationsAsMap);
}
@Override
@Nullable
public MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName) {
return getAllAnnotationAttributes(annotationName, false);
}
// 这个和getMergedAnnotationAttributes有关
@Override
@Nullable
public MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName, boolean classValuesAsString) {
return AnnotatedElementUtils.getAllAnnotationAttributes(this.introspectedMethod,
annotationName, classValuesAsString, this.nestedAnnotationsAsMap);
}
}
最后关于AnnotationMetadataReadingVisitor
和MethodMetadataReadingVisitor
,它俩都实现了xxxVisitor
接口的,和Spring中处理ASM技术有关,不在本文讨论的范围之内,暂且略过。
Spring内部使用得字节码技术,比如
SimpleMetadataReader
,CachingMetadataReaderFactory
等等
它是一个访问ClassMetadata
等的简单门面。它的唯一实现SimpleMetadataReader
内部实现原理就是基于AnnotationMetadataReadingVisitor
使用ASM相关的
public interface MetadataReader {
// 返回此Class来自的资源(创建的时候需要指定此资源,然后交给`AnnotationMetadataReadingVisitor`去处理)
Resource getResource();
// ClassMeta,实现为通过`AnnotationMetadataReadingVisitor`中获取
ClassMetadata getClassMetadata();
// 注解元信息 也是通过`AnnotationMetadataReadingVisitor`获取
AnnotationMetadata getAnnotationMetadata();
}
Metadata
在框架中往往是个很重要的概念,不仅仅是Spring,MyBatis
、Hibernate
等流行框架中都有类似的元数据的概念。它能让我们更容器的操控一些底层的描述性属性,从而做不同的逻辑判断处理。从而就能使得框架有更强的包容能力
从上课件,元数据JDK提供的和Spring提供的还是不太一样的。但是Spring大部分都是基于JDK的封装和适配,然后给到一个Spring自己内部的类。这也是Spring在到处都是适配器模式
的典型应用
最后,关于Spring中ASM技术处理元数据以及其余的应用场景,肯定会有专门的大篇幅来讲述,因为那将是一个很大的话题,也是一个很难的专题