描述
在ClassPathBeanDefinitionScanner中看到spring通過掃描給定的包路徑,獲取到對應(yīng)的class資源并判斷是否生成BeanDefinition注冊到IOC容器中逼裆,接下來根據(jù)源碼來看spring是怎么通過class資源生成元數(shù)據(jù)
ClassPathBeanDefinitionScanner分析中看到 MetadataReaderFactory.getMetadataReader方法通過class資源(resource)生成MetadataReader
// 此處通過asm將class文件讀取成元數(shù)據(jù)模型
MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
下面跟讀MetadataReaderFactory與MetadataReader代碼查看class生成元數(shù)據(jù)。
MetadataReaderFactory
MetadataReaderFactory接口 ,MetadataReader的工廠接口抖锥。
允許緩存每個MetadataReader的元數(shù)據(jù)集碎罚。
- 類關(guān)系圖
public interface MetadataReaderFactory {
/**
* 根據(jù)class名稱創(chuàng)建MetadataReader
*/
MetadataReader getMetadataReader(String className) throws IOException;
/**
* 根據(jù)class的Resource創(chuàng)建MetadataReader
*/
MetadataReader getMetadataReader(Resource resource) throws IOException;
}
MetadataReaderFactory接口提供兩個方法:
- 根據(jù)class名稱生成MetadataReader
- 根據(jù)class的Resource生成MetadataReader
- SimpleMetadataReaderFactory
public class SimpleMetadataReaderFactory implements MetadataReaderFactory {
// 資源加載器磅废,此類根據(jù)路徑將給定的path生成IO流資源
private final ResourceLoader resourceLoader;
@Override
public MetadataReader getMetadataReader(String className) throws IOException {
try {
//根據(jù)classname生成class對應(yīng)的資源路徑
String resourcePath = ResourceLoader.CLASSPATH_URL_PREFIX +
ClassUtils.convertClassNameToResourcePath(className) + ClassUtils.CLASS_FILE_SUFFIX;
//獲取classname的IO流資源
Resource resource = this.resourceLoader.getResource(resourcePath);
//調(diào)用資源創(chuàng)建MetadataReader
return getMetadataReader(resource);
}
catch (FileNotFoundException ex) {
}
}
/**
* 根據(jù)class資源創(chuàng)建MetadataReader 默認(rèn)實(shí)現(xiàn)
*/
@Override
public MetadataReader getMetadataReader(Resource resource) throws IOException {
return new SimpleMetadataReader(resource, this.resourceLoader.getClassLoader());
}
}
SimpleMetadataReaderFactory類為MetadataReaderFactory的簡單實(shí)現(xiàn),默認(rèn)實(shí)現(xiàn)了MetadataReaderFactory的兩個方法
- 在getMetadataReader(String className) 方法中根據(jù)className創(chuàng)建class的Resource荆烈,然后調(diào)用getMetadataReader(Resource resource)
- 在getMetadataReader(Resource resource) 方法中默認(rèn)創(chuàng)建了SimpleMetadataReader
- CachingMetadataReaderFactory
public class CachingMetadataReaderFactory extends SimpleMetadataReaderFactory {
//默認(rèn)的緩存大小
public static final int DEFAULT_CACHE_LIMIT = 256;
//內(nèi)存緩存列表拯勉,Resource-MetadataReader的映射緩存
@Nullable
private Map<Resource, MetadataReader> metadataReaderCache;
@Override
public 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);
}
}
}
CachingMetadataReaderFactory 類在SimpleMetadataReaderFactory的基礎(chǔ)上增加了緩存功能,對Resource-MetadataReader的映射做了本地緩存
MetadataReader
spring 對MetadataReader的描述為:Simple facade for accessing class metadata,as read by an ASM.大意是通過ASM讀取class IO流資源組裝訪問元數(shù)據(jù)的門面接口
- 類關(guān)系圖
- MetadataReader
public interface MetadataReader {
/**
* 返回class文件的IO資源引用
*/
Resource getResource();
/**
* 為基礎(chǔ)class讀取基本類元數(shù)據(jù)憔购,返回基礎(chǔ)類的元數(shù)據(jù)宫峦。
*/
ClassMetadata getClassMetadata();
/**
*為基礎(chǔ)類讀取完整的注釋元數(shù)據(jù),包括注釋方法的元數(shù)據(jù)玫鸟。返回基礎(chǔ)類的完整注釋元數(shù)據(jù)
*/
AnnotationMetadata getAnnotationMetadata();
}
MetadataReader接口提供三個方法:
- 返回class文件的IO資源引用
- 返回基礎(chǔ)類的元數(shù)據(jù)
- 返回基礎(chǔ)類的完整注釋元數(shù)據(jù)
- SimpleMetadataReader
final class SimpleMetadataReader implements MetadataReader {
//class類IO流資源引用
private final Resource resource;
//class類元數(shù)據(jù)
private final ClassMetadata classMetadata;
//class類完整注釋元數(shù)據(jù)
private final AnnotationMetadata annotationMetadata;
/**
* 構(gòu)建函數(shù)导绷,用于通過過ASM字節(jié)碼操控框架讀取class讀取class資源流
*/
SimpleMetadataReader(Resource resource, @Nullable ClassLoader classLoader) throws IOException {
// 獲取class類IO流
InputStream is = new BufferedInputStream(resource.getInputStream());
ClassReader classReader;
try {
//通過ASM字節(jié)碼操控框架讀取class
classReader = new ClassReader(is);
}
catch (IllegalArgumentException ex) {
}
finally {
is.close();
}
//注解元數(shù)據(jù)讀取訪問者讀取注解元數(shù)據(jù)
AnnotationMetadataReadingVisitor visitor = new AnnotationMetadataReadingVisitor(classLoader);
classReader.accept(visitor,ClassReader.SKIP_DEBUG);
//注解元數(shù)據(jù)
this.annotationMetadata = visitor;
//class元數(shù)據(jù)
this.classMetadata = visitor;
this.resource = resource;
}
@Override
public Resource getResource() {
return this.resource;
}
@Override
public ClassMetadata getClassMetadata() {
//返回當(dāng)前類元數(shù)據(jù)
return this.classMetadata;
}
@Override
public AnnotationMetadata getAnnotationMetadata() {
//返回當(dāng)前類的注解元數(shù)據(jù)
return this.annotationMetadata;
}
}
SimpleMetadataReader 為MetadataReader的默認(rèn)實(shí)現(xiàn),在創(chuàng)建SimpleMetadataReader通過ASM字節(jié)碼操控框架讀取class讀取class資源流生成classMetadata與annotationMetadata
元數(shù)據(jù)模型
類元數(shù)據(jù)模型在包org.springframework.core.type下屎飘,是spring對class文件的描述單元妥曲,包含ClassMetadata,MethodMetadata钦购,AnnotationMetadata等元數(shù)據(jù)檐盟,都是對外提供對class屬性的訪問,同時這些元數(shù)據(jù)是通過ASM字節(jié)碼框架解析字節(jié)碼獲取生成押桃。
- ClassMetadata
提供對class類的信息訪問
public interface ClassMetadata {
//返回當(dāng)前class名稱
String getClassName();
//返回當(dāng)前class是否為接口
boolean isInterface();
//返回當(dāng)前class是否為注解
boolean isAnnotation();
//返回當(dāng)前class是否為抽象類
boolean isAbstract();
boolean isConcrete();
//返回當(dāng)前class是否為final修飾
boolean isFinal();
boolean isIndependent();
boolean hasEnclosingClass();
String getEnclosingClassName();
boolean hasSuperClass();
String getSuperClassName();
String[] getInterfaceNames();
String[] getMemberClassNames();
}
- AnnotationMetadata
提供對class類里的注解信息訪問
public interface AnnotationMetadata extends ClassMetadata, AnnotatedTypeMetadata {
Set<String> getAnnotationTypes();
Set<String> getMetaAnnotationTypes(String annotationName);
boolean hasAnnotation(String annotationName);
boolean hasMetaAnnotation(String metaAnnotationName);
boolean hasAnnotatedMethods(String annotationName);
Set<MethodMetadata> getAnnotatedMethods(String annotationName);
}
- MethodMetadata
提供對class類里方法信息的訪問
public interface MethodMetadata extends AnnotatedTypeMetadata {
String getMethodName();
String getDeclaringClassName();
String getReturnTypeName();
boolean isAbstract();
boolean isStatic();
boolean isFinal();
boolean isOverridable();
}
通過ClassPathBeanDefinitionScanner與生成元數(shù)據(jù)流程部分我們可以看到spring對class的完整操作
- 將class文件生成IO流的Resource
- 通過ASM字節(jié)碼框架根據(jù)Resource創(chuàng)建元數(shù)據(jù)模型
- 根據(jù)元數(shù)據(jù)模型以及Resource生成BeanDefinition(bean定義)