ByteBuddyを使用すると、別のインスタンスを呼び出して結果を変換して1つのインスタンスメソッドを実装できますか?例えばByteBuddyを使用したチェーン/トランスフォームメソッドの呼び出し
(玩具例):
上述したpublic abstract class Foo {
public String bar() {
return "bar";
}
public abstract int baz();
}
、私はそれがbar()
を呼び出し、返された文字列の長さを返しbaz
ように実装することができますか?それはあたかも、すなわち:
public int baz() {
return bar().length();
}
単純に、私は次のことを試してみました:
Method bar = Foo.class.getDeclaredMethod("bar");
Method baz = Foo.class.getDeclaredMethod("baz");
Method length = String.class.getDeclaredMethod("length");
Foo foo = new ByteBuddy()
.subclass(Foo.class)
.method(ElementMatchers.is(baz))
.intercept(
MethodCall.invoke(bar) // call bar()...
.andThen(MethodCall.invoke(length)) // ... .length()?
).make()
.load(Foo.class.getClassLoader())
.getLoaded()
.newInstance();
System.out.println(foo.baz());
私はandThen()
は、最初の呼び出しの戻り値に呼び出された考えで間違っていたようにしかし、それが見えます。生成されたインスタンスで呼び出されたようです。
Exception in thread "main" java.lang.IllegalStateException:
Cannot invoke public int java.lang.String.length() on class Foo$ByteBuddy$sVgjXXp9
at net.bytebuddy.implementation.MethodCall$MethodInvoker$ForContextualInvocation
.invoke(MethodCall.java:1667)
Iはまた、インターセプタを試みた:
class BazInterceptor {
public static int barLength(@This Foo foo) {
String bar = foo.bar();
return bar.length();
}
}
で:
Foo foo = new ByteBuddy()
.subclass(Foo.class)
.method(ElementMatchers.is(baz))
.intercept(MethodDelegation.to(new BazInterceptor()))
// ...etc.
これは実行が、無意味な結果870698190
を生じ、そしてbarLength()
にブレークポイントを設定および/または印刷ステートメントを追加それは決して呼ばれていないことを示唆した。あまりにも明確に私は迎撃者または@This
を正しく理解していません。
ByteBuddyに1つのメソッドを呼び出し、その戻り値で別のメソッドを呼び出す方法はありますか?
k5_'s answerパー:BazInterceptor
作品であればいずれか:
- 我々は、上記のように、
new BazInterceptor()
に委任しますが、インスタンスメソッド、またはbarLength()
ます - たちはクラスメソッド
barLength()
ままにし、インスタンスではなくBazInterceptor.class
に委譲します。
私は実際にチェックしていなかったけれども、私は、870698190
はBazInterceptor
インスタンスのhashCode()
に委任した疑い。
ありがとうございました。この場合は2番目のオプションを使用しますが、最初のオプションがインターセプタインスタンスがある状態を持つ必要がある状況でも機能することを知っておくとよいでしょう。 –