カスタマイズされたバイト コードを使用してクラスを作成しています。このために、ビルトインを使用することはできませんがInstrumentation
、コンストラクター用の特定のバイト コードを作成する独自のインストルメンテーションを作成する必要があります。これはもちろん Byte Buddy に実装できますが、生成されたクラスの詳細がすべてわかっている場合は、 javacInstrumentation
を使用してこのクラスをコンパイルすることをお勧めします。API について学びたいと思いますが、これは作成しようとしている実際のクラスではありません。
サンプル クラスでは、コンストラクターの desugared バージョンに相当するものを実装する必要があります。コンストラクターは Java ランタイムのメソッドにすぎませんが、JVM の検証機能によって適用される特定のセマンティクスに従います。脱糖コンストラクタは次のようになります。
public GeneratedByByteBuddy(int a) {
super();
this.a = a;
return;
}
このまったく同じクラスの Byte Buddy 実装は次のようになります。
new ByteBuddy()
.subclass(Object.class, ConstructorStrategy.Default.NO_CONSTRUCTORS)
.name("my.company.GeneratedByByteBuddy")
.defineField("a", int.class, Visibility.PRIVATE, FieldManifestation.FINAL)
.defineConstructor(Arrays.<Class<?>>asList(int.class), Visibility.PUBLIC)
.intercept(new Instrumentation() {
@Override
public InstrumentedType prepare(InstrumentedType instrumentedType) {
return instrumentedType;
}
@Override
public ByteCodeAppender appender(final Target instrumentationTarget) {
return new ByteCodeAppender() {
@Override
public boolean appendsCode() {
return true;
}
@Override
public Size apply(MethodVisitor methodVisitor,
Context instrumentationContext,
MethodDescription instrumentedMethod) {
StackManipulation.Size size = new StackManipulation.Compound(
MethodVariableAccess.REFERENCE.loadFromIndex(0),
MethodInvocation.invoke(new TypeDescription.ForLoadedType(Object.class)
.getDeclaredMethods()
.filter(isConstructor().and(takesArguments(0))).getOnly()),
MethodVariableAccess.REFERENCE.loadFromIndex(0),
MethodVariableAccess.INTEGER.loadFromIndex(1),
FieldAccess.forField(instrumentationTarget.getTypeDescription()
.getDeclaredFields()
.named("a"))
.putter(),
MethodReturn.VOID
).apply(methodVisitor, instrumentationContext);
return new Size(size.getMaximalSize(), instrumentedMethod.getStackSize());
}
};
}
})
.make()
.load(getClass().getClassLoader(), ClassLoadingStrategy.Default.INJECTION);
各メソッドの実装はInstrumentation
、フィールドまたはメソッドを追加して作成された型を変更できる によって実装されます。これは、クラスには必要ありません。次に、ByteCodeAppender
バイトコード命令の書き込みに使用される を発行します。