java - 生成从另一个类调用静态方法并使用多个字段作为参数的代码
问题描述
我一直在努力寻找解决这个问题的方法。希望你能帮助我。
我正在尝试使用一些已定义的字段生成一个从另一个类调用静态方法的方法:
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
并尝试使用 a 解决问题List
不是一种选择。
解决方案
您正在调用 vararg 方法,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 字节码。
推荐阅读
- javascript - 从多个 CSV 文件读取并使用流写入一个
- python - 日历程序垂直打印一周中的几天,需要水平打印
- jenkins-pipeline - 更改 repo 签出代理以在管道中读取 Jenkinsfile
- xamarin - 如何根据文本是否溢出来更改标签文本 - 在 Xamarin 表单中
- javascript - 每次加载后自动刷新页面
- javascript - 检测何时从 JS 添加的样式表应用了 CSS 规则
- javascript - Flatlist 项目在模态框内不可点击
- ios - Swift/ObjC:尝试从对象中插入 nil 对象[1]
- amazon-web-services - 导入 AWS::ApiGateway::Authorizer 无服务器框架
- python - xbbg 给出“无法连接到彭博”错误