是否可以使用@Advice.OnMethodEnter从方法返回?

问题描述 投票:0回答:1

使用 Byte Buddy 的建议 API,是否可以从检测的方法返回而不实际执行它?

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

@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
方法吗?

java byte-buddy
1个回答
6
投票

不,这是不可能的,返回值只能从退出建议中设置。但是,如果值已经存在,则可以通过跳过原始方法来模拟;如果输入建议定义了值,则可以通过从退出建议中设置该值来模拟:

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.Argument(0) String query,
          @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 可以使用建议类作为模板并内联字节代码,无需太多工作即可避免运行时开销。

© www.soinside.com 2019 - 2024. All rights reserved.