我正在尝试使用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*/);
我有几个问题:
ByteBuddy是否为开箱即用提供了一些合适的实施方案?
是否提供了开箱即用的ByteBuddy实现类概述?
如果没有这样的实现开箱即用,我会很感激有关如何使我自己的实现实例满足我的目的的一些提示。
答案 0 :(得分:0)
没有找到任何准备好的实现,所以最终编写自己的。它尚未最终确定,但它确实有效。这是:
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;
}
}
我会暂时搁置这个问题,因为有人知道更好的解决方案。
答案 1 :(得分:0)
您可以通过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
的默认构造函数)。参数索引必须是分配给该字段的参数的索引(从零开始)。