是否可以从使用@Advice.OnMethodEnter 的方法中return?

Is it possible to return from a method using @Advice.OnMethodEnter?

使用 Byte Buddy 的建议 API,是否可以从检测方法中 return 而无需实际执行它?

一个用例是实现缓存并 return 缓存值(如果存在),而不是再次计算该值。

@Advice.OnMethodEnter
public static Object returnCachedValue(@Advice.Argument(0) String query) {
    if (cache.containsKey(query)) {
        // should "abort" method call
        return cache.get(query);
    }
}

我知道上面的代码示例只是创建了一个局部变量,我可以在 @Advice.OnMethodExit 方法中获取它。但是有没有办法在显式 return 上中止方法调用?如果是,这是否也适用于 void 方法?

不,这是不可能的,return 值只能从退出通知中设置。但是它可以通过在值已经存在的情况下跳过原始方法来模拟,并且在输入建议定义值的情况下通过从退出建议中设置该值来模拟:

class MyAdvice {
  @Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class)
  public static Object returnCachedValue(@Advice.Argument(0) String query) {
    if (cache.containsKey(query)) {
      return cache.get(query);
    } else {
      return null;
    }
  }

  @Advice.OnMethodExit
  public static void processCachedValue(
          @Advice.Return(readOnly = false, typing = DYNAMIC) Object returned,
          @Advice.Enter Object enter) {
    if (enter != null) {
      returned = enter;
    } else {
      cache.put(query, returned);
    }
  }
}

当然,如果缓存值是null,这就不行了。为避免这种情况,您可以在某些实例中包装该值,以确保输入的值永远不会是 null。这样做还可以将上述模式用于 void 方法。

这可能看起来不方便编程,但建议的想法是 Byte Buddy 可以使用建议 class 作为模板并内联字节代码而无需太多工作以避免运行时开销。