いいえ、あなたは何も見逃していません。
Byte Buddy でコードを操作すると、この操作はアプリケーションのスタック トレースに反映されます。これは意図的なもので、何か問題が発生した場合のデバッグがはるかに簡単になります。ログ インターセプターが実行時例外をスローすることを考えてみてください。インターセプトが何らかの方法で元のメソッドにマージされた場合、他の開発者が理解するのは非常に混乱します。Byte Buddy のアプローチでは、インターセプターが実際にそこから利用できるため、原因となっているソースに簡単に移動できます。Byte Buddy を使用すると、生成されたコードから例外がスローされることはなく、問題をソース コードにまでさかのぼることができます。
また、スタック フレームをマージすると、呼び出し元に依存するコードに奇妙な副作用が生じる可能性があります。たとえば、セキュリティ マネージャーは、インターセプトされたコードよりもインターセプターに高いアクセス許可を与える場合があります。スタック フレームをマージすると、これらの権限が元に戻ります。
注入されたインターセプターを@Super Callable
記述することは、アラウンドアドバイスを実装するための標準的な方法です。パフォーマンスについても心配する必要はありません。Byte Buddy は、スーパー メソッド呼び出しがオーバーヘッドなしで実行される可能性が最も高いように、JIT コンパイラが非常に簡単にコードをインライン化できるように記述されています。(それを示すベンチマークもあります。)あなたの例では、一般的なarround-adivceは次のようになります。
public class TimingInterceptor {
@RuntimeType
public static Object intercept(@Super Callable<?> zuper)
throws Exception {
long before = System.currentTimeMillis();
try {
return zuper.call();
} finally {
System.out.println("Took: " + (Systen.currentTimeMillis() - before));
}
}
}
すべてのメソッドについて、実行にかかる時間がコンソールに出力されるようになりました。を使用してこのコードに委任しますMethodDelegation.to(TimingInterceptor.class)
。
@RuntimeType
注釈を必ず使用してください。このように、Byte Buddy は実行時にキャストを試行し、この一般的な傍受を可能にします。