Spring對很多常用的基本對象進(jìn)行了封裝和擴(kuò)充,其中部分適用于平時(shí)開發(fā)使。這里記錄下Spring封裝的何種元數(shù)據(jù)接口。需要注意,以下參數(shù)或者返回的結(jié)果中的類名都為全限定名。
ClassMetadata
對Class的一層封裝。
String getClassName();
boolean isInterface();
boolean isAnnotation();
boolean isAbstract();
//非接口非抽象類
boolean isConcrete();
boolean isFinal();
boolean isIndependent();
//是否有外部類,即本身是否是內(nèi)部類
boolean hasEnclosingClass();
//外部類的全限定名
@Nullable
String getEnclosingClassName();
boolean hasSuperClass();
@Nullable
String getSuperClassName();
String[] getInterfaceNames();
//包含的所有內(nèi)部類
String[] getMemberClassNames();
StandardClassMetadata是基于ClassAPI實(shí)現(xiàn)了該接口。
AnnotatedTypeMetadata
java的反射包里有一個(gè)接口AnnotatedElement,Spring對該接口做了進(jìn)一步的封裝,是AnnotationMetadata以及MethodMetadata的父接口。雖然沒有直接繼承的實(shí)現(xiàn)類,但該接口的實(shí)現(xiàn)都是調(diào)用工具類AnnotatedElementUtils的靜態(tài)方法實(shí)現(xiàn)的。平時(shí)在處理注解的也可以用AnnotatedElementUtils或者AnnotationUtils提供的方法,這兩個(gè)工具類會(huì)對結(jié)果進(jìn)行緩存,稍微減少重復(fù)讀取時(shí)反射調(diào)用的資源消耗。這兩個(gè)工具方法的實(shí)現(xiàn)比較復(fù)雜,但public的靜態(tài)方法的方法名都盡量做到了所見即所得,也有比較詳細(xì)的注釋,需要注意的是get和find兩者語義的不同,get的查找范圍僅限定于本身,而find則會(huì)在父類、實(shí)現(xiàn)的接口(對類而言);父類的方法、接口的方法、橋接方法(重載泛型方法會(huì)出現(xiàn))查找。
//目標(biāo)元素上是否有注解
boolean isAnnotated(String annotationName);
//目標(biāo)元素上某注解的屬性值
@Nullable
Map<String, Object> getAnnotationAttributes(String annotationName);
//目標(biāo)元素上某注解的屬性值
@Nullable
Map<String, Object> getAnnotationAttributes(String annotationName, boolean classValuesAsString);
@Nullable
MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName);
@Nullable
MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName, boolean classValuesAsString);
MethodMetadata
方法的元數(shù)據(jù),接口繼承了AnnotatedTypeMetadata從而可以獲取方法上的注解信息。
String getMethodName();
//定義方法的類全限定名
String getDeclaringClassName();
//返回值的全限定名
String getReturnTypeName();
boolean isAbstract();
boolean isStatic();
boolean isFinal();
//也就是沒有被標(biāo)記為static final private
boolean isOverridable();
StandardMethodMetadata基于標(biāo)準(zhǔn)java反射以及AnnotatedElementUtils的方法實(shí)現(xiàn)了該接口。
AnnotationMetadata
接口繼承了ClassMetadata以及AnnotatedTypeMetadata,提供類的元數(shù)據(jù)以及類的注解的元數(shù)據(jù)。
//獲取所有注解的全限定名
Set<String> getAnnotationTypes();
//獲取每個(gè)注解上的元注解
Set<String> getMetaAnnotationTypes(String annotationName);
boolean hasAnnotation(String annotationName);
//類上的注解中是否包含元注解
boolean hasMetaAnnotation(String metaAnnotationName);
boolean hasAnnotatedMethods(String annotationName);
Set<MethodMetadata> getAnnotatedMethods(String annotationName);
實(shí)現(xiàn)類是StandardAnnotationMetadata,同樣是基于java反射API和AnnotatedElementUtils實(shí)現(xiàn)。
MetadataReader
該接口對Class的元數(shù)據(jù)做了一個(gè)get方法的封裝,方便一次性獲取所有需要的數(shù)據(jù)。
public interface MetadataReader {
Resource getResource();
ClassMetadata getClassMetadata();
AnnotationMetadata getAnnotationMetadata();
}
接口的實(shí)現(xiàn)是包類外部是不可見的,就不記錄了。獲取實(shí)例是通過工廠類獲取的。Spring提供了兩個(gè)工廠類的實(shí)現(xiàn):SimpleMetadataReaderFactory、CachingMetadataReaderFactory,這兩個(gè)工廠類實(shí)現(xiàn)類工廠接口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在讀取的時(shí)候會(huì)做一次緩存,默認(rèn)緩存256和實(shí)例,淘汰規(guī)則是FIFO。