美文网首页
spring之class读取生成元数据流程

spring之class读取生成元数据流程

作者: Mr_1214 | 来源:发表于2018-12-06 12:56 被阅读107次

    描述

    在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的元数据集。

    • 类关系图
    metaReaderFactory.png
    public interface MetadataReaderFactory {
        /**
         * 根据class名称创建MetadataReader
         */
        MetadataReader getMetadataReader(String className) throws IOException;
    
        /**
         * 根据class的Resource创建MetadataReader
         */
        MetadataReader getMetadataReader(Resource resource) throws IOException;
    
    }
    

    MetadataReaderFactory接口提供两个方法:

    1. 根据class名称生成MetadataReader
    2. 根据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.png
    • MetadataReader
    public interface MetadataReader {
    
        /**
         * 返回class文件的IO资源引用
         */
        Resource getResource();
    
        /**
         * 为基础class读取基本类元数据,返回基础类的元数据。
         */
        ClassMetadata getClassMetadata();
    
        /**
         *为基础类读取完整的注释元数据,包括注释方法的元数据。返回基础类的完整注释元数据
         */
        AnnotationMetadata getAnnotationMetadata();
    }
    

    MetadataReader接口提供三个方法:

    1. 返回class文件的IO资源引用
    2. 返回基础类的元数据
    3. 返回基础类的完整注释元数据
    • 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的完整操作

    1. 将class文件生成IO流的Resource
    2. 通过ASM字节码框架根据Resource创建元数据模型
    3. 根据元数据模型以及Resource生成BeanDefinition(bean定义)

    相关文章

      网友评论

          本文标题:spring之class读取生成元数据流程

          本文链接:https://www.haomeiwen.com/subject/yrzncqtx.html