Last active
December 21, 2020 18:27
-
-
Save ljnelson/0bf33635b8a1404d47d42747045b5960 to your computer and use it in GitHub Desktop.
A recipe for sketching out ByteBuddy proxy objects
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import net.bytebuddy.description.modifier.Visibility; | |
import net.bytebuddy.dynamic.DynamicType; | |
import net.bytebuddy.implementation.FieldAccessor; | |
import net.bytebuddy.implementation.MethodCall; | |
import static net.bytebuddy.implementation.MethodCall.invoke; | |
import static net.bytebuddy.matcher.ElementMatchers.named; | |
DynamicType.Builder<?> builder = //... acquire the builder, then: | |
.defineField("proxiedInstance", theClassBeingProxied, Visibility.PRIVATE) // (1) | |
.implement(new DefaultParameterizedType(null, Proxy.class, theClassBeingProxied)) // (2) | |
.intercept(FieldAccessor.ofBeanProperty()) // (3) | |
.method(someMatcher) // (4) | |
.intercept(invoke(MethodCall.MethodLocator.ForInstrumentedMethod.INSTANCE) // (5) | |
.onMethodCall(invoke(named("getProxiedInstance"))) | |
.withAllArguments()); | |
// 1: Adds a field to the proxy class named proxiedInstance. It will hold the "real" object. | |
// 2: Proxy.class is a made-up interface defining getProxiedInstance()/setProxiedInstance(T), | |
// where T is the type of the thing being proxied; e.g. Proxy<Frob>. | |
// DefaultParameterizedType is a made-up implementation of java.lang.reflect.ParameterizedType. | |
// 3: Magic ByteBuddy incantation to implement the Proxy<Frob> interface by making two methods | |
// that read from and write to the proxiedInstance field just defined | |
// 4: Choose what methods to intercept here; see the net.bytebuddy.matcher.ElementMatchers class | |
// in particular | |
// 5: The serious magic is here. It means, roughly, "whatever the method the user just called, | |
// turn around and invoke it on the return value of the getProxiedInstance() method with all | |
// of the arguments the user originally supplied". That INSTANCE object is not documented | |
// anywhere, really; you just have to know that it is suitable for use here in this DSL | |
// "sentence". |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hello,
To be compliant with all methods, you need to add a call to
MethodCall.withAllArguments
. This adds all arguments of the instrumented method as arguments to the invoked method...