手写Spring源码04 - 元数据读取器 MetadataReader 设计与实现(三)

本篇记录类的读取与访问的设计与实现,如下图圈出的部分:
在这里插入图片描述

类的读取和访问实现

Spring使用了ASM框架对类进行读取,并且将ASM代码嵌在了Spring框架里。ASM是一个Java字节码操作和分析框架,可以对字节码进行读取,读到类的方法、注解、内部类、超类等等信息。

这里直接加了ASM的依赖,这里就包括了ClassReader、ClassVisitor、AnnotationVisitor、MethodVisitor

<!-- https://mvnrepository.com/artifact/org.ow2.asm/asm -->
<dependency>
    <groupId>org.ow2.asm</groupId>
    <artifactId>asm</artifactId>
    <version>9.1</version>
</dependency>
类的访问者实现 - SimpleAnnotationMetadataReadingVisitor

SimpleAnnotationMetadataReadingVisitor继承了类的访问者ClassVisitor,重写了访问注解和方法的访问方法,返回了自定义的注解访问者(MergedAnnotationReadingVisitor)和方法访问者(SimpleMethodMetadataReadingVisitor)

代码实现:

package cn.zhanghongyang.core.type.classreader;

import cn.zhanghongyang.core.annotation.MergedAnnotation;
import cn.zhanghongyang.core.annotation.MergedAnnotations;
import cn.zhanghongyang.core.type.MethodMetadata;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

import java.util.ArrayList;
import java.util.List;

/**
 * @Author: zhanghongyang
 * @Description: 类访问者(实现类)
 */
public class SimpleAnnotationMetadataReadingVisitor extends ClassVisitor {

    private String className;

    private int access;

    private List<MergedAnnotation> annotations = new ArrayList<>();

    private List<MethodMetadata> annotatedMethod = new ArrayList<>();

    private SimpleAnnotationMetadata metadata;

    public SimpleAnnotationMetadataReadingVisitor() {
        super(Opcodes.ASM8);
    }


    @Override
    public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
        this.className = name.replace("/", ".");
        this.access = access;
    }


    @Override
    public void visitOuterClass(String owner, String name, String descriptor) {
        //外部类回调
        System.out.printf("visitOuterClass回调,owner:%s, name:%s, descriptor:%s \n", owner, name, descriptor);
    }


    @Override
    public void visitInnerClass(String name, String outerName, String innerName, int access) {
        //内部类回调
        System.out.printf("visitInnerClass回调,name:%s, outerName:%s, innerName:%s, access:%d \n", name, outerName, innerName, access);
    }

    /**
     * 访问者注解回调
     * @param descriptor 注解名称 Ljava/lang/annotation/Target;
     * @param visible 是否可见
     * @return
     */
    @Override
    public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
        //获取类的注解,添加到annotations
        return MergedAnnotationReadingVisitor.get(this.className, descriptor, visible, this.annotations::add);
    }

    @Override
    public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
        return new SimpleMethodMetadataReadingVisitor(this.className, access, name, descriptor, this.annotatedMethod::add);
    }

    @Override
    public void visitEnd() {
        //访问结束将结果封装成SimpleAnnotationMetadata
        MergedAnnotations annotations = MergedAnnotations.of(this.annotations);
        this.metadata = new SimpleAnnotationMetadata(this.className, this.access, null, null,
                false, null, null, this.annotatedMethod.toArray(new MethodMetadata[0]), annotations);
    }

    public SimpleAnnotationMetadata getMetadata() {
        return metadata;
    }
}
合并注解访问者实现 - MergedAnnotationReadingVisitor

代码实现:

package cn.zhanghongyang.core.type.classreader;

import cn.zhanghongyang.core.annotation.AnnotationFilter;
import cn.zhanghongyang.core.annotation.MergedAnnotation;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;

import java.lang.annotation.Annotation;
import java.util.function.Consumer;

/**
 * @Author: zhanghongyang
 * @Description: 注解访问者(实现类)
 */
public class MergedAnnotationReadingVisitor<T extends Annotation> extends AnnotationVisitor {

    /** 注解来源类全称 */
    private String source;

    /** 注解类型 */
    private Class<T> annotationType;

    /**
     * 访问结束回调函数,MergedAnnotation保存了注解的信息
     */
    private Consumer<MergedAnnotation> consumer;

    /**
     * 获取注解访问者
     * @param source 注解所属类
     * @param descriptor 访问回调的描述,可用获取到注解的名称
     * @param visible 是否可以访问
     * @param consumer 注解访问结束的回调
     * @return
     */
    public static AnnotationVisitor get(String source, String descriptor, boolean visible, Consumer<MergedAnnotation> consumer){
        if(!visible){
            return null;
        }

        String typeName = Type.getType(descriptor).getClassName();
        //对注解进行过滤
        if (AnnotationFilter.PLAIN.matches(typeName)){
            return null;
        }
        try {
            Class className = Class.forName(typeName);
            return new MergedAnnotationReadingVisitor(source, className, consumer);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

    public MergedAnnotationReadingVisitor(String source, Class<T> annotationType, Consumer<MergedAnnotation> consumer) {
        super(Opcodes.ASM8);
        this.source = source;
        this.annotationType = annotationType;
        this.consumer = consumer;
    }


    @Override
    public void visitEnd() {
        //将注解封装成MergedAnnotation
        MergedAnnotation annotation = MergedAnnotation.of(this.source, this.annotationType);
        //通过回调函数带回结果
        this.consumer.accept(annotation);
    }
}

方法访问者实现 - SimpleMethodMetadataReadingVisitor

代码实现:

package cn.zhanghongyang.core.type.classreader;

import cn.zhanghongyang.core.type.MethodMetadata;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;

import java.util.function.Consumer;

/**
 * @Author: zhanghongyang
 * @Description: 方法访问者
 */
public class SimpleMethodMetadataReadingVisitor extends MethodVisitor {

    /** 所属类的名称 **/
    private String declaringClassName;

    private int access;

    private String name;

    private String descriptor;

    private Consumer<MethodMetadata> consumer;


    public SimpleMethodMetadataReadingVisitor(String declaringClassName, int access, String name, String descriptor, Consumer<MethodMetadata> consumer) {
        super(Opcodes.ASM8);
        this.declaringClassName = declaringClassName;
        this.access = access;
        this.name = name;
        this.descriptor = descriptor;
        this.consumer = consumer;
    }

    @Override
    public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
        return super.visitAnnotation(descriptor, visible);
    }

    @Override
    public void visitEnd() {
        String returnTypeName = Type.getReturnType(this.descriptor).getClassName();
        SimpleMethodMetadata metadata = new SimpleMethodMetadata(this.name, this.access, this.declaringClassName, returnTypeName);
        this.consumer.accept(metadata);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值