不,你没有错过任何东西。
每当您使用 Byte Buddy 操作代码时,此操作将反映在应用程序的堆栈跟踪中。这是故意的,因为它使调试更容易,以防出现问题。想想你的日志拦截器抛出运行时异常;如果拦截以某种方式合并到您的原始方法中,那么其他开发人员很难弄清楚。使用 Byte Buddy 的方法,您可以简单地导航到导致源,因为您的拦截器实际上可以从那里获得。使用 Byte Buddy,生成的代码不会引发异常,因此任何问题都可以追溯到源代码。
此外,合并堆栈帧可能会对调用者敏感代码产生奇怪的副作用。例如,安全管理员可能会授予拦截器比截获代码更高的权限。合并堆栈帧将恢复这些权限。
编写带有@Super Callable
注入的拦截器是实现 arround-advice 的规范方法。也不用担心性能。Byte Buddy 的编写方式使得 JIT 编译器很容易内联代码,这样超级方法调用很可能以零开销执行。(甚至有一个基准证明了这一点。)对于您的示例,通用 arround-advce 如下所示:
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 在运行时尝试进行强制转换,从而使这种通用拦截成为可能。