# 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
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
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
2
3
4
5
6
7
8
9
这些模式表明,可以将树 API 仅用于方法,将核心 API 用于类。在实践中经常使用这一策略。