首页 > 解决方案 > 可以使用 ByteBuddy 而不是被调用的方法来检测方法调用吗?

问题描述

我想替换一些保护对java.lang.System某些用户代码的调用的 AspectJ 代码。 java.lang.System不能/不应该被检测。

使用 AspectJ 的解决方案是像以下示例一样检测调用代码。应该保护的代码将被检测,而允许的代码则不被检测。

@Around("call(public long java.lang.System.currentTimeMillis()) && within(io.someuserdomain..*) && !within(io.someotherdomain..*))
def aroundSystemcurrentTimeMillis(wrapped: ProceedingJoinPoint): Long = {
      throw new IllegalStateException("must not call System.currentTimeMillis in usercode")
}

有没有办法使用 ByteBuddy 做同样的事情?到目前为止,我只找到了有关如何检测被调用者而不是调用者的示例。

标签: javascalaaspectjbyte-buddy

解决方案


您目前可以通过注册 a 来替换方法或字段访问,MemberSubstitution但与 AspectJ 相比,这些功能仍然有限。例如,不可能像您的示例代码那样抛出异常。但是,您可以委托给包含引发异常的代码的方法:

MemberSubstitution.relaxed()
  .method(named("currentTimeMillis"))
  .replaceWith(MyClass.class.getMethod("throwException"))
  .in(any());

上述替换将用对以下成员的调用替换任何方法调用:

public class MyClass {
  public static long throwException() {
    throw new IllegalStateException();
  }
}

替换将应用于应用访问者的任何方法。您可以注册一个AgentBuilder.Default来构建一个 Java 代理,或者查看 Byte Buddy 的构建插件。


推荐阅读