A ClassVisitor
представляет этап обработки, тогда как ClassNode
представляет конкретное состояние класса. Чтобы интегрировать операцию, работающую с ClassNode
, вам нужен посетитель, который создает дерево при посещении класса и начинает посещать обработанный результат в конце.
public abstract class IntegrateNodeTransformer extends ClassVisitor {
ClassVisitor target;
public IntegrateNodeTransformer(int api, ClassVisitor target) {
super(api, null);
this.target = target;
}
/**
* Initiate the building of a tree when the visit of a class starts.
*/
@Override
public void visit(int version, int access, String name, String signature,
String superName, String[] interfaces) {
super.cv = new ClassNode();
super.visit(version, access, name, signature, superName, interfaces);
}
/**
* On completion of visiting the source class, process the tree and initiate
* visiting of the result by the target visitor, if there is one.
*/
@Override
public void visitEnd() {
super.visitEnd();
ClassNode source = (ClassNode)super.cv;
ClassNode result = process(source);
if(target != null) result.accept(target);
}
/**
* Do the actual work with the Tree API.
* May manipulate {@code source} directly and return it or return an entirely new tree.
*/
protected abstract ClassNode process(ClassNode source);
}
Если у вас есть только один шаг обработкииспользуя Tree API, вы можете рассмотреть возможность его непосредственного выполнения без преобразования в ClassVisitor
:
ClassReader cr = new ClassReader(…);
// steps before using the tree API
// mind that composed visitor process in the opposite order of their construction
ClassNode cn = new ClassNode();
ClassVisitor cv = new SomeClassVisitor(cn); // 3rd step
cv = new AnotherClassVisitor(cv); // 2nd step
cv = new YetAnotherClassVisitor(cv); // 1st step
cr.accept(cv, 0); // perform steps 1 to 3 and build result tree
cn = process(cn); // the Tree API based operation (4th step)
// steps after using the tree API
ClassWriter cw = new ClassWriter(cr, 0); // last generate class
cv = new YourLastClassVisitor(cw); // 7th step
cv = new InCaseYouHaveMoreClassVisitor(cv); // 6th step
cv = new YouKnowWhatIMean(cv); // 5th step
cn.accept(cv); // perform steps 5 to 7 on tree input and generate class
final byte[] code = cw.toByteArray();