前为止,我们仅看到了如何创建和转换 MethodNode 对象,却还没有看到与类的字节数组表示进行链接。和类的情景一样,这一链接过程也是通过合成核心 API 和树 API 组件完成的,本节就来进行解释。
除了图 7.1 显示的字段之外,MethodNode 类扩展了 MethodVisitor 类,还提供了两个 accept 方法,它以一个 MethodVisitor 或一个 ClassVisitor 为参数。accept 方法基于 MethodNode 字段值生成事件,而 MethodVisitor 方法执行逆操作,即根据接收到的事件设定 MethodNode 字段。
和类的情景一样,有可能与核心 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);
}
}
而基于委托的模式为:
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);
}
}
第一种模式的一种变体是直接在 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);
}
};
}
这些模式表明,可以将树 API 仅用于方法,将核心 API 用于类。在实践中经常使用这一策略。