ASM学习系列(二)

系列文章目录

ASM学习系列(一)



前言

前一篇文章中介绍了ASM中的一些基本操作,本篇文章的主题是介绍一下ASM中所使用的设计模式,在了解完本篇文章的内容后,相信大家会对ASM有一些新的认识和了解。


一、访问者模式

ASM库中使用的设计模式为访问者模式,该模式的主要目的是要将数据和对数据的操作进行一个分离,简单的来说,就是针对不同的数据,都有一个单独的数据操作对象。使用这种设计模式,可以规避多重的if-else使用来进行数据类型判断,他的UML类图可以描述为:

![在这里插入图片描述](https://img-blog.csdnimg.cn/31b847cdfcdf41c88c6fddce5ca5f5b6.png
从上图可以看出,我们可以针对不同的数据类型,在真正的访问者(AVisitor)中重写不同的visit方法,根据不同的参数类型,可以调用不同的方法,这样就省去了通过if-else进行类型判断的过程,数据的读取可以由数据类中accept使用访问者对该类中的数据进行操作,上述的过程可以由如下代码表示:
首先创建一个接口Data:

public interface Data {
    
    
    void accept(Visitor visitor);
}

有两个Data的实现类,AData和BData:

public class AData implements Data{
    
    
    int a1 = 100;
    int a2 = 200;
    int a3 = 300;

    @Override
    public void accept(Visitor visitor) {
    
    
        visitor.visit(this);
    }
}
public class BData implements Data {
    
    
    int b1 = 100;
    int b2 = 200;
    int b3 = 300;

    public void accept(Visitor visitor) {
    
    
        visitor.visit(this);
    }
}

一个数据的集合,同时包含一个读取数据的方法:

public class DataStruct {
    
    
    AData aData = new AData();
    BData bData = new BData();

    void readData(Visitor visitor) {
    
    
        aData.accept(visitor);
        bData.accept(visitor);
    }
}

以上就是和数据有关的类,以下为与数据操作相关的类:

public interface Visitor {
    
    
    void visit(AData data);
    void visit(BData data);
}

数据访问者的实现类AVisitor:

public class AVisitor implements Visitor {
    
    
    @Override
    public void visit(AData data) {
    
    
        System.out.println("a1: " + data.a1 + " a2: " + data.a2 + " a3: " + data.a3);
    }

    @Override
    public void visit(BData data) {
    
    
        System.out.println("b1: " + data.b1 + " b2: " + data.b2 + " b3: " + data.b3);
    }
}

然后我们创建一个client,如下:

public class Client {
    
    
    public static void main(String[] args) {
    
    
        DataStruct data = new DataStruct();
        data.readData(new AVisitor());
    }
}

最后可以得到打印输出:

a1: 100 a2: 200 a3: 300
b1: 100 b2: 200 b3: 300

可以看出通过这样的方式对数据进行操作,可以实现数据和数据操作对象的解耦。

二、ASM实例分析

在ASM中,我们会看到如下代码:

ClassPrinter cp = new ClassPrinter();	//ClassVisitor的实现类
ClassReader cr = new ClassReader("java.lang.Boolean");
cr.accept(cp, 0);

其中ClassPrinter为ClassVisitor的一个实现类,如下:

class ClassPrinter extends ClassVisitor {
    
    
    public ClassPrinter() {
    
    
        super(ASM4);
    }

    @Override
    public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
    
    
        super.visit(version, access, name, signature, superName, interfaces);
        System.out.println(name + " extends " + superName + "{");
    }

    @Override
    public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) {
    
    
        System.out.println(" " + descriptor + " " + name);
        return super.visitField(access, name, descriptor, signature, value);
    }

    @Override
    public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
    
    
        System.out.println(" " + name + descriptor);
        return super.visitMethod(access, name, descriptor, signature, exceptions);
    }

    @Override
    public void visitEnd() {
    
    
        super.visitEnd();
        System.out.println("}");
    }
}

这里就对应了第一节中的Visitor和AVisitor。ClassReader就是数据类,对应了Data,可以调用他的accept方法使用Visitor来访问数据。
除此以外,在ASM中一个很有意思的地方是可以将多个ClassVisitor组合起来进行使用,这里他是在每个ClassVisitor的成员变量中还放了一个ClassVisitor对象。也就是说,可以在构造数据的时候,可以使用成员变量中的ClassVisitor的访问逻辑,当然在此基础上,也可以添加自己的逻辑,比如说,在ASM学习系列(一) 中,移除或增添变量的时候,还使用了TraceClassVisitor这个类的访问数据的功能。

总结

以上就是这篇文章的内容,本文主要介绍了ASM所使用的设计模式,在了解了该模式后,可以对理解ASM的架构和使用ASM都有很大的帮助。

猜你喜欢

转载自blog.csdn.net/qq_42788340/article/details/125892974
ASM