This is perfectly possible when using a Java agent in combination with Byte Buddy. For example, you can modify the GpioFactory::getInstance
method as demonstrated by the following Java agent:
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.
}
}
Using this agent, Any controller instance that is returned from the original getInstance
method would be passed through the MyFactory::intercept
method.
Alternatively, you can equally instrument all implementations of GpioController
to directly do the logging. This would then affect all instances of the interface.
If you do not have the possibility to add a Java agent at startup, on JDKs (not standard JVMs), you can use ByteBuddyAgent.install()
(from the byte-buddy-agent
dependency) to manually install an agent at runtime. In this case, you need to make sure however that the agent is installed before the GpioFactory
is loaded. You can find more information in the documentation of the library.
Finally, note that AspectJ and Byte Buddy both use a Java agent to achieve their instrumentation. AspectJ does however use its own syntax where Byte Buddy models its API in Java what is the main core difference.