描述
在ClassPathBeanDefinitionScanner中看到spring通过扫描给定的包路径,获取到对应的class资源并判断是否生成BeanDefinition注册到IOC容器中,接下来根据源码来看spring是怎么通过class资源生成元数据
ClassPathBeanDefinitionScanner分析中看到 MetadataReaderFactory.getMetadataReader方法通过class资源(resource)生成MetadataReader
// 此处通过asm将class文件读取成元数据模型
MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
下面跟读MetadataReaderFactory与MetadataReader代码查看class生成元数据。
MetadataReaderFactory
MetadataReaderFactory接口 ,MetadataReader的工厂接口。
允许缓存每个MetadataReader的元数据集。
- 类关系图
public interface MetadataReaderFactory {
/**
* 根据class名称创建MetadataReader
*/
MetadataReader getMetadataReader(String className) throws IOException;
/**
* 根据class的Resource创建MetadataReader
*/
MetadataReader getMetadataReader(Resource resource) throws IOException;
}
MetadataReaderFactory接口提供两个方法:
- 根据class名称生成MetadataReader
- 根据class的Resource生成MetadataReader
- SimpleMetadataReaderFactory
public class SimpleMetadataReaderFactory implements MetadataReaderFactory {
// 资源加载器,此类根据路径将给定的path生成IO流资源
private final ResourceLoader resourceLoader;
@Override
public MetadataReader getMetadataReader(String className) throws IOException {
try {
//根据classname生成class对应的资源路径
String resourcePath = ResourceLoader.CLASSPATH_URL_PREFIX +
ClassUtils.convertClassNameToResourcePath(className) + ClassUtils.CLASS_FILE_SUFFIX;
//获取classname的IO流资源
Resource resource = this.resourceLoader.getResource(resourcePath);
//调用资源创建MetadataReader
return getMetadataReader(resource);
}
catch (FileNotFoundException ex) {
}
}
/**
* 根据class资源创建MetadataReader 默认实现
*/
@Override
public MetadataReader getMetadataReader(Resource resource) throws IOException {
return new SimpleMetadataReader(resource, this.resourceLoader.getClassLoader());
}
}
SimpleMetadataReaderFactory类为MetadataReaderFactory的简单实现,默认实现了MetadataReaderFactory的两个方法
- 在getMetadataReader(String className) 方法中根据className创建class的Resource,然后调用getMetadataReader(Resource resource)
- 在getMetadataReader(Resource resource) 方法中默认创建了SimpleMetadataReader
- CachingMetadataReaderFactory
public class CachingMetadataReaderFactory extends SimpleMetadataReaderFactory {
//默认的缓存大小
public static final int DEFAULT_CACHE_LIMIT = 256;
//内存缓存列表,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的基础上增加了缓存功能,对Resource-MetadataReader的映射做了本地缓存
MetadataReader
spring 对MetadataReader的描述为:Simple facade for accessing class metadata,as read by an ASM.大意是通过ASM读取class IO流资源组装访问元数据的门面接口
- 类关系图
- 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;
}
}
SimpleMetadataReader 为MetadataReader的默认实现,在创建SimpleMetadataReader通过ASM字节码操控框架读取class读取class资源流生成classMetadata与annotationMetadata
元数据模型
类元数据模型在包org.springframework.core.type下,是spring对class文件的描述单元,包含ClassMetadata,MethodMetadata,AnnotationMetadata等元数据,都是对外提供对class属性的访问,同时这些元数据是通过ASM字节码框架解析字节码获取生成。
- ClassMetadata
提供对class类的信息访问
public interface ClassMetadata {
//返回当前class名称
String getClassName();
//返回当前class是否为接口
boolean isInterface();
//返回当前class是否为注解
boolean isAnnotation();
//返回当前class是否为抽象类
boolean isAbstract();
boolean isConcrete();
//返回当前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与生成元数据流程部分我们可以看到spring对class的完整操作
- 将class文件生成IO流的Resource
- 通过ASM字节码框架根据Resource创建元数据模型
- 根据元数据模型以及Resource生成BeanDefinition(bean定义)
网友评论