Reputation: 341
Let's have simple interface:
public interface Person {
String getFirstName();
void setFirstName(String firstName);
}
Now I create proxy this way:
public class TestClass {
@Test
public void testMethod() throws InstantiationException, IllegalAccessException {
final Class<?> proxy = new ByteBuddy().subclass(Object.class).implement(Person.class)
// AND INTERCEPTS ALL ABSTRACT AND OBJECT DEFAULT METHODS
// AND TRAP ALL METHODS EXCEPT CONSTRUCTORS AND FINALIZER
.method(
ElementMatchers.isAbstract()
)
// AND DELEGATE CALL TO OUR INVOCATION HANDLER STORED IN PRIVATE FIELD OF THE CLASS
.intercept(MethodDelegation.to(Delegator.class))
// NOW CREATE THE BYTE-CODE
.make()
// AND LOAD IT IN CURRENT CLASSLOADER
.load(TestClass.class.getClassLoader())
// RETURN
.getLoaded();
final Person theInstance = (Person) proxy.newInstance();
theInstance.setFirstName("ABC");
theInstance.getFirstName();
}
public static class Delegator {
@RuntimeType
public static Object intercept(@This Object proxy, @Origin Method method, @AllArguments Object[] args) throws Throwable {
System.out.println("Intercept A: " + proxy + ", " + method + ", " + args);
return null;
}
@RuntimeType
public static Object intercept(@This Object proxy, @Origin Method method) throws Throwable {
System.out.println("Intercept B: " + proxy + ", " + method);
return null;
}
@RuntimeType
public static Object interceptE(@This Object proxy, @DefaultMethod(nullIfImpossible = true) Method defaultMethod, @SuperMethod(nullIfImpossible = true) Method superMethod) throws Throwable {
System.out.println("Intercept C: " + proxy + ", " + defaultMethod + ", " + superMethod);
return null;
}
@RuntimeType
public static Object interceptE(@This Object proxy, @DefaultMethod(nullIfImpossible = true) Method defaultMethod, @SuperMethod(nullIfImpossible = true) Method superMethod, @AllArguments Object[] args) throws Throwable {
System.out.println("Intercept D: " + proxy + ", " + defaultMethod + ", " + superMethod + ", " + args);
return null;
}
}
}
When I execute the test I see this output:
Intercept C: net.bytebuddy.renamed.java.lang.Object$ByteBuddy$MVjuc1JA@147ed70f, null, null
Intercept C: net.bytebuddy.renamed.java.lang.Object$ByteBuddy$MVjuc1JA@147ed70f, null, null
It seems that I cannot ever access method signature of the called method if it originates in interface and is not implemented by the superclass?!
Also I would expect that when I call theInstance.setFirstName("ABC");
I would see Intercept D:
which also accepts all input arguments.
What do I miss here? I read the documentation but I'm still confused.
In general I want to create Delegator
that catches all methods in proxied class and handles following situtations:
For this I would need access to the:
How do I achieve that?
Upvotes: 1
Views: 500
Reputation: 341
Auch - the problem is that some annotations are declared twice in ByteBuddy in different packages - for example:
net.bytebuddy.implementation.bind.annotation.AllArguments
net.bytebuddy.asm.Advice.AllArguments
When annotation from the implementation
package is used, everything works. That's a nasty catch!
Upvotes: 2