我正在尝试操纵静态方法。为此,可以使用Byte Buddy或任何其他框架。
有一个名为Pi4J的库用于控制Raspberry Pi的GPIO。该库有一个名为:
的方法GpioController gpio = GpioFactory.getInstance();
在我可能无法控制的程序的几个地方调用此调用,以便我需要修改调用。
我想要做的是,当GpioFactory.getInstance
以某种方式执行时,检测并修改GpioController
的方法,以便记录它们已被调用。
也许唯一的解决方案是使用AspectJ,但是你知道Byte Buddy是否可以成为解决方案吗?
答案 0 :(得分:2)
Pi4J的代码在LGPL许可下的github上是开源的。您可以简单地克隆存储库,根据需要进行修改并使用自己的版本。如果您认为您的更改可以帮助其他人并考虑贡献tp pi4j。
答案 1 :(得分:2)
将Java agent与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
的所有实现以直接执行日志记录。这将影响界面的所有实例。
如果您无法在启动时在JDK(非标准JVM)上添加Java代理,则可以使用ByteBuddyAgent.install()
(来自byte-buddy-agent
依赖关系)手动安装代理运行。在这种情况下,您需要确保在加载GpioFactory
之前已安装代理。您可以在documentation of the library。
最后,请注意AspectJ和Byte Buddy都使用Java代理来实现其检测。然而,AspectJ使用自己的语法,其中Byte Buddy用Java模拟其API的主要核心差异。