gpt4 book ai didi

java - 生成从另一个类调用静态方法并使用多个字段作为参数的代码

转载 作者:太空宇宙 更新时间:2023-11-04 09:02:05 25 4
gpt4 key购买 nike

我一直在努力寻找解决这个问题的方法。希望你能帮助我。

我正在尝试生成一个方法,该方法使用一些已定义的字段从另一个类调用静态方法:

class Test {
private String someField;
private String otherField;
}

预期结果:

class Test {
private String someField;
private String otherField;

public String getCacheKey() {
return SimpleCacheKey.of(this.someField, this.otherField);
}
}

class SimpleCacheKey {
public static String of(final Object... values) {
// Some Operations
return computed_string;
}
}

我尝试了几件事,最接近的一个:

public class ModelProcessor implements Plugin {
@Override
public Builder<?> apply(final Builder<?> builder,
final TypeDescription typeDescription,
final ClassFileLocator classFileLocator) {

return builder.defineMethod("getCacheKey", String.class, Visibility.PUBLIC)
.intercept(new SimpleCacheKeyImplementation());
}

@Override
public void close() throws IOException {

}

@Override
public boolean matches(final TypeDescription typeDefinitions) {
return true;
}
}

public class SimpleCacheKeyImplementation implements Implementation {
private static final MethodDescription SIMPLE_CACHE_KEY_OF = getOf();

@SneakyThrows
private static MethodDescription.ForLoadedMethod getOf() {
return new MethodDescription.ForLoadedMethod(SimpleCacheKey.class.getDeclaredMethod("of", Object[].class));
}

@Override
public InstrumentedType prepare(final InstrumentedType instrumentedType) {
return instrumentedType;
}

@Override
public ByteCodeAppender appender(final Target implementationTarget) {
final TypeDescription thisType = implementationTarget.getInstrumentedType();

return new ByteCodeAppender.Simple(Arrays.asList(
// first param
MethodVariableAccess.loadThis(),
this.getField(thisType, "someField"),

// second param
MethodVariableAccess.loadThis(),
this.getField(thisType, "otherField"),

// call of and return the result
MethodInvocation.invoke(SIMPLE_CACHE_KEY_OF),
MethodReturn.of(TypeDescription.STRING)
));
}

private StackManipulation getField(final TypeDescription thisType, final String name) {
return FieldAccess.forField(thisType.getDeclaredFields()
.filter(ElementMatchers.named(name))
.getOnly()
).read();
}
}

但是生成的代码如下(用Intellij Idea反编译):

public String getCacheKey() {
String var10000 = this.name;
return SimpleCacheKey.of(this.someValue);
}

更改 SimpleCacheKey.of 的签名并尝试使用 List 解决问题不是一个选择。

最佳答案

你正在调用一个可变参数方法,java字节码没有这个。因此,您需要创建一个正确类型的实际数组来调用该方法。

@Override
public ByteCodeAppender appender(final Target implementationTarget) {
final TypeDescription thisType = implementationTarget.getInstrumentedType();

return new ByteCodeAppender.Simple(Arrays.asList(ArrayFactory.forType(TypeDescription.Generic.OBJECT)
.withValues(Arrays.asList( //
new StackManipulation.Compound(MethodVariableAccess.loadThis(),
this.getField(thisType, "field1")),
new StackManipulation.Compound(MethodVariableAccess.loadThis(),
this.getField(thisType, "field2")))
), MethodInvocation.invoke(SIMPLE_CACHE_KEY_OF) //
, MethodReturn.of(TypeDescription.STRING)));

}

也许 byte-buddy 有一个特殊的构建器来实现这一点,但至少这是实现这一目标的一种方法。

Imo:编写要生成的字节码的 java 版本通常是一个好方法。这样您就可以比较 javac 字节码和 bytebuddy 字节码。

关于java - 生成从另一个类调用静态方法并使用多个字段作为参数的代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60695798/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com