AnnotationMetadata、 MethodMetadata

元数据:数据的数据 比如Class就是一种元数据
Metadata在org.springframework.core.type包名下,该包内类不多,主要有以下相关接口和类:
所以我们看到顶层接口有两个:ClassMetadata和AnnotatedTypeMetadata

顶层接口:ClassMetadata和AnnotatedTypeMetadata
一、ClassMetadata
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

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
AnnotatedTypeMetadata:对AnnotatedElement的封装适配

      它没有Standard的实现(毕竟AnnotatedElement也是接口,没办法做基础实现的),但是它有两个非常重要的子接口:AnnotationMetadata和
MethodMetadata 这两个接口是Spring内部的直接运用。
     java的反射包里有一个接口AnnotatedElement,Spring对该接口做了进一步的封装。虽没直接继承的实现类,但该接口的实现都是调用工具类
AnnotatedElementUtils的静态方法实现的。平时在处理注解的也可以用AnnotatedElementUtils或者AnnotationUtils提供的方法,这两个工具类会对
结果进行缓存,稍微减少重复读取时反射调用的资源消耗。这两个工具方法的实现比较复杂,但public的静态方法的方法名都尽量做到了所见即所得,也有
比较详细的注释,需要注意的是get和find两者语义的不同,get的查找范围仅限定于本身,而find则会在父类、实现的接口(对类而言);父类的方法、接
口的方法、桥接方法(重载泛型方法会出现)查找。

二级接口AnnotationMetadata和MethodMetadata
这两个元数据接口,在Spring内部非常常用,需要掌握。前者Spring2.5就有了,后者Spring3.0才有的

(1)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);
}

主要实现类:StandardAnnotationMetadata 、AnnotationMetadataReadingVisitor
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 接口的方法 因为实现很简单 此处就省略掉了
	
}

(2)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();
}

主要实现类:StandardMethodMetadata、MethodMetadataReadingVisitor

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技术有关

三、MetadataReader接口
它的默认实现SimpleMetadataReader,内部实现原理就是基于AnnotationMetadataReadingVisitor使用ASM相关的,该接口对Class的元数据做了一个get方法的封装,方便一次性获取所有需要的数据。

public interface MetadataReader {

	// 返回此Class来自的资源(创建的时候需要指定此资源,然后交给`AnnotationMetadataReadingVisitor`去处理)
	Resource getResource();
	// ClassMeta,实现为通过`AnnotationMetadataReadingVisitor`中获取
	ClassMetadata getClassMetadata();
	// 注解元信息 也是通过`AnnotationMetadataReadingVisitor`获取
	AnnotationMetadata getAnnotationMetadata();

}

接口的实现是包类外部是不可见的,就不记录了。获取实例是通过工厂类获取的。Spring提供了两个工厂类的实现:SimpleMetadataReaderFactory、CachingMetadataReaderFactory,这两个工厂类实现类工厂接口MetadataReaderFactory:

public interface MetadataReaderFactory {
 
/**
 * Obtain a MetadataReader for the given class name.
 * @param className the class name (to be resolved to a ".class" file)
 * @return a holder for the ClassReader instance (never {@code null})
 * @throws IOException in case of I/O failure
 */
MetadataReader getMetadataReader(String className) throws IOException;
 
/**
 * Obtain a MetadataReader for the given resource.
 * @param resource the resource (pointing to a ".class" file)
 * @return a holder for the ClassReader instance (never {@code null})
 * @throws IOException in case of I/O failure
 */
MetadataReader getMetadataReader(Resource resource) throws IOException;
 
}

顾名思义,CachingMetadataReaderFactory在读取的时候会做一次缓存,默认缓存256和实例,淘汰规则是FIFO。

总结
Metadata在框架中往往是个很重要的概念,不仅仅是Spring,MyBatis、Hibernate等流行框架中都有类似的元数据的概念。它能让我们更容器的操控一些底层的描述性属性,从而做不同的逻辑判断处理。从而就能使得框架有更强的包容能力

元数据JDK提供的和Spring提供的还是不太一样的。但是Spring大部分都是基于JDK的封装和适配,然后给到一个Spring自己内部的类。这也是Spring在到处都是适配器模式的典型应用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值