gpt4 book ai didi

java - 使用 MethodDelegation 实现环绕通知

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:17:10 26 4
gpt4 key购买 nike

我对这里描述的方法委托(delegate)非常感兴趣:

http://www.javacodegeeks.com/2015/01/make-agents-not-frameworks.html

这很好用:

.intercept(MethodDelegation.to(LogInterceptor.class)
.andThen(SuperMethodCall.INSTANCE)

我可以拦截调用并捕获传递给方法的参数,这是我想要实现的一半。但是,我还没有找到一种同样简洁的方法来捕获返回值。我知道我可以将 Callable 传递给执行调用的拦截器,但沿着这条路走似乎肯定会弄乱我的堆栈跟踪。

在我看来,应该有一种简单且规范的方式来实现“around-method”模式。

在开始深入研究 API 之前:我是不是漏掉了什么?

最佳答案

不,你没有遗漏任何东西。

无论何时使用 Byte Buddy 操作代码,此操作都会反射(reflect)在应用程序的堆栈跟踪中。这是有意为之的,因为它使调试更容易,以防出现问题。想想你的日志拦截器抛出一个运行时异常;如果拦截以某种方式合并到您的原始方法中,这会让其他开发人员感到困惑。使用 Byte Buddy 的方法,您可以简单地导航到导致源,因为您的拦截器实际上可以从那里获得。使用 Byte Buddy,生成的代码不会抛出任何异常,因此任何问题都可以追溯到源代码。

此外,合并堆栈帧会对调用者敏感代码产生奇怪的副作用。例如,安全管理器可能会授予拦截器比拦截代码更高的权限。合并堆栈帧将恢复这些权限。

编写一个注入(inject)@Super Callable 的拦截器是实现 arround-advice 的规范方式。也不用担心性能。 Byte Buddy 的编写方式使 JIT 编译器很容易内联代码,这样 super 方法调用很可能以零开销执行。 (甚至还有 a benchmark demonstrating that 。)对于您的示例,通用 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) 委托(delegate)此代码。

确保使用 @RuntimeType 注释。这样,Byte Buddy 会尝试在运行时进行转换,从而使这种通用拦截成为可能。

关于java - 使用 MethodDelegation 实现环绕通知,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33743867/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com