簡體   English   中英

在ByteBuddy中從頭開始創建一個類構造函數

[英]Create a class constructor from scratch in ByteBuddy

我正在嘗試使用ByteBuddy從頭開始創建Java類。 一個類應該有一堆私有的final屬性和一個構造函數,它們使用傳遞的參數初始化它們。 我開始時:

DynamicType.Builder<?> builder = new ByteBuddy()
                .subclass(Object.class)
                .implement(Serializable.class)
                .modifiers(Visibility.PUBLIC, TypeManifestation.FINAL)
                .name("Structure");

// for each property to be declared
builder = builder.defineField(bindingName, bindingType, visibility.PRIVATE, FieldManifestation.FINAL);
// end of for

builder = builder.defineConstructor(Visibility.PUBLIC)
                .withParameters(bindings)
                .intercept(/* Some implementation is supposed to go here*/);

我有幾個問題:

  1. ByteBuddy是否為開箱即用提供了一些合適的實現?

  2. 是否存在開箱即用的ByteBuddy實現類概述?

  3. 如果沒有這樣的實現開箱即用,我會感謝你提供一些關於如何使我自己的實現實例服務於我的目的的提示。

沒有找到任何准備好的實現,所以最終寫我自己的。 它尚未最終確定,但它確實有效。 這里是:

final class ConstructorImplementation implements Implementation {

    static private final class BCA implements ByteCodeAppender {

        @Override
        public Size apply(MethodVisitor methodVisitor, Context implementationContext, MethodDescription instrumentedMethod) {
            TypeDescription instrumentedType = implementationContext.getInstrumentedType();
            Iterator<? extends ParameterDescription> iterator = instrumentedMethod.getParameters().iterator();

            List<StackManipulation> insr = new ArrayList<>();
            insr.add(MethodVariableAccess.loadThis());
            insr.add(MethodInvocation.invoke(TypeDescription.OBJECT.getDeclaredMethods().get(0)));
            for (FieldDescription.InDefinedShape field : instrumentedType.getDeclaredFields()) {
                ParameterDescription.InDefinedShape param = iterator.next().asDefined();
                insr.add(MethodVariableAccess.loadThis());
                insr.add(MethodVariableAccess.load(param));
                insr.add(FieldAccess.forField(field).write());
            }
            insr.add(MethodReturn.VOID);

            StackManipulation.Size operandStackSize = new StackManipulation.Compound(
                    insr
            ).apply(methodVisitor, implementationContext);
            return new Size(operandStackSize.getMaximalSize(),
                    instrumentedMethod.getStackSize());
        }
    }

    private final BCA bca;

    public ConstructorImplementation() {
        bca = new BCA();
    }

    @Override
    public ByteCodeAppender appender(Target implementationTarget) {
        return bca;
    }

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

我會暫時擱置這個問題,因為有人知道更好的解決方案。

您可以通過MethodCallFieldAccessor的組合MethodCall實現這樣的構造FieldAccessor

DynamicType.Builder<?> builder = ...;
Implementation interceptor = StubMethod.INSTANCE;

// for each field
builder = builder.defineField(bindingName, 
              bindingType, visibility.PRIVATE, FieldManifestation.FINAL);
interceptor = FieldAccessor.ofField(bindingName)
                  .setsArgumentAt( ... )
                  .andThen(interceptor);

interceptor = MethodCall.invoke( ... ).andThen(interceptor);

方法調用必須調用已檢測類或超類構造函數的特定構造函數(可能是Object的默認構造函數)。 參數索引必須是分配給該字段的參數的索引(從零開始)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM