# 7.2 组件合成

前为止,我们仅看到了如何创建和转换 MethodNode 对象,却还没有看到与类的字节数组表示进行链接。和类的情景一样,这一链接过程也是通过合成核心 API 和树 API 组件完成的,本节就来进行解释。

# 7.2.1 介绍

除了图 7.1 显示的字段之外,MethodNode 类扩展了 MethodVisitor 类,还提供了两个 accept 方法,它以一个 MethodVisitor 或一个 ClassVisitor 为参数。accept 方法基于 MethodNode 字段值生成事件,而 MethodVisitor 方法执行逆操作,即根据接收到的事件设定 MethodNode 字段。

# 7.2.2 模式

和类的情景一样,有可能与核心 API 使用一个基于树的方法转换器,比如一个方法适配器。用于类的两种模式实际上对于方法也是有效的,其工作方式完全相同。基于继承的模式如下:

public class MyMethodAdapter extends MethodNode {
    public MyMethodAdapter(int access, String name, String desc, String signature, String[] exceptions, MethodVisitor mv) {
        super(ASM4, access, name, desc, signature, exceptions);
        this.mv = mv;
    }

    @Override
    public void visitEnd() {
        // 将你的转换代码放在这儿
        accept(mv);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12

而基于委托的模式为:

public class MyMethodAdapter extends MethodVisitor {
    MethodVisitor next;

    public MyMethodAdapter(int access, String name, String desc, String signature, String[] exceptions, MethodVisitor mv) {
        super(ASM4,
                new MethodNode(access, name, desc, signature, exceptions));
        next = mv;
    }

    @Override
    public void visitEnd() {
        MethodNode mn = (MethodNode) mv;
        //将你的转换代码放在这儿
        mn.accept(next);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

第一种模式的一种变体是直接在 ClassAdapter 的 visitMethod 中将它与一个匿名内部类一起使用:

public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
    return new MethodNode(ASM4, access, name, desc, signature, exceptions) {
        @Override
        public void visitEnd() {
            //将你的转换代码放在这儿
            accept(cv);
        }
    };
}
1
2
3
4
5
6
7
8
9

这些模式表明,可以将树 API 仅用于方法,将核心 API 用于类。在实践中经常使用这一策略