开发者社区> 问答> 正文

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

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

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

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。

问题来源:Stack Overflow

展开
收起
montos 2020-03-24 09:29:59 611 0
1 条回答
写回答
取消 提交回答
  • 您正在调用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字节码。

    回答来源:Stack Overflow

    2020-03-24 09:30:37
    赞同 展开评论 打赏
问答地址:
问答排行榜
最热
最新

相关电子书

更多
建立联系方法之一 立即下载
继承与功能组合 立即下载
低代码开发师(初级)实战教程 立即下载