2

我正在尝试操作静态方法。为此,可以使用Byte Buddy或任何其他框架。

有一个名为Pi4J的库用于控制 Raspberry Pi 的 GPIO。这个库有一个方法叫做:

GpioController gpio = GpioFactory.getInstance();

并且在我可能无法控制的程序的多个位置调用此调用,因此我需要修改调用。

我想做的是当GpioFactory.getInstance以某种方式执行时检测并修改它们的方法,GpioController以便它们记录它们已被调用。

也许唯一的解决方案是使用 AspectJ,但是您知道 Byte Buddy 是否可以成为解决方案吗?

4

2 回答 2

2

将Java 代理Byte Buddy结合使用时,这是完全可能的。例如,您可以修改GpioFactory::getInstance方法,如下面的 Java 代理所示:

public class MyAgent {
  public static void premain(String arg, Instrumentation inst) {
    new AgentBuilder.Default()
      .type(ElementMatchers.named("com.pi4j.io.gpio.GpioFactory")
      .transform((builder, type) -> // Or anonymous class for pre Java 8
          builder.method(ElementMatchers.named("getInstance"))
                 .intercept(MethodDelegation.to(MyFactory.class));
      ).installOn(inst)
  }
}

public class MyFactory {
  public static GpioController intercept(@SuperCall Callable<GpioController> s) 
       throws Exception {
    return s.call(); // Wrap controller here.
  }
}

使用此代理,从原始方法返回的任何控制器实例getInstance都将通过该MyFactory::intercept方法传递。

或者,您可以同样检测 的所有实现GpioController以直接进行日志记录。这将影响接口的所有实例。

如果您无法在启动时添加 Java 代理,则在 JDK(不是标准 JVM)上,您可以使用ByteBuddyAgent.install()(来自byte-buddy-agent依赖项)在运行时手动安装代理。在这种情况下,您需要确保在加载之前安装了代理您可以在库的文档中GpioFactory找到更多信息。

最后,请注意 AspectJ 和 Byte Buddy 都使用 Java 代理来实现它们的检测。然而,AspectJ 确实使用自己的语法,其中 Byte Buddy 用 Ja​​va 建模其 API,这是主要的核心区别。

于 2015-12-28T10:55:40.740 回答
2

Pi4J的代码在 LGPL 许可下在 github 上开源。您可以简单地克隆存储库,根据需要进行修改并使用自己的版本。如果您觉得您的更改可以帮助其他人,请考虑贡献 tp pi4j。

于 2015-12-27T11:27:38.057 回答