我正在使用Java通过反射来修改一些常规代码。
原始groovy代码的格式为:
void method() {
A(processId);
B();
}
我需要修改它以注入processId:
void callMethod() {
int processId = rand();
invokeMethod(
{->
A(processId);
B();
}, processId);
}
void invokeMethod(Closure closure, int processId) {
doSomething(processId);
closure.call();
}
注意:invokeMethod()是现有方法,不会被注入。
当我如上所述修改原始代码时,出现此错误: “ groovy.lang.MissingPropertyException:无此类属性:processId”
我尝试将“ callMethod”方法的variableScope设置为包括“ processId”变量作为DeclaredVariable。
作为参考,这是我用来执行此操作的代码:
private void wrapMethod(@NonNull MethodNode node)
{
VariableExpression var = new VariableExpression("processId", new ClassNode(Integer.class));
var.setClosureSharedVariable(true);
//Generate a statement that creates a processId
Statement statement = GeneralUtils.declS(var, GeneralUtils.callThisX("getUUID"));
ClosureExpression methodClosure = createMethodClosure(node);
ArgumentListExpression args = createArgumentListExpression(methodClosure,
varX("processId"));
MethodCallExpression method = GeneralUtils.callThisX("invokeMethod", args);
BlockStatement newMethodCode = GeneralUtils.block(statement, GeneralUtils.stmt(method));
newMethodCode.setVariableScope(methodClosure.getVariableScope().copy());
//Just to be safe, modifying the scope of the node as well.
VariableScope newScope = node.getVariableScope().copy();
newScope.putDeclaredVariable(var);
node.setCode(newMethodCode);
node.setVariableScope(newScope);
}
private ClosureExpression createMethodClosure(MethodNode node) {
//Get code from within node to dump into a closure.
BlockStatement block = (BlockStatement) node.getCode();
//Setting closureScope and adding processId
VariableScope closureScope = block.getVariableScope().copy();
closureScope.getReferencedLocalVariablesIterator()
.forEachRemaining(x -> x.setClosureSharedVariable(true));
Variable var = new VariableExpression("processId", new ClassNode(Integer.class));
var.setClosureSharedVariable(true);
closureScope.putDeclaredVariable(var);
ClosureExpression methodClosure = GeneralUtils.closureX(block);
methodClosure.setVariableScope(closureScope);
return methodClosure;
}
我已经验证了代码,以检查是否可以在invokeMethod()块中访问“ processId”,并且注入的结果代码是否符合预期。
关于为什么这种方法无效的任何想法?