Reputation: 49
I have a method which has arguments an object instance and a string which represents the name of a method, with the following signature:
Object executeDynamicMethod(Object instance, String methodName);
I can easily execute the method by name by using reflection, something like the following:
Method methodToExecute = instance.getClass().getMethod(methodName...);
methodToExecute.invoke(); ...
However, what happens when the instance is a proxied one, and the method is running though an invocation handler? Then the instance object Class here has not the method and I can not get it and invoke it. Additionally, I don't want to use Proxy.getInvocationHandler(instance) because sometimes the instance is proxied, but sometimes not, and I don't want to spoil it with if statements.
Thus, is there any way to invoke a method by its name on an instance without having to retrieve the method from the class first? Thanks.
Upvotes: 2
Views: 2781
Reputation: 341
I had a similar problem. In my case i have implemented a Proxy that delegates to a „real“ object (For caching reasons). But sometimes the delegate was also Proxy. However, in this Proxy a have to invoke sometimes a method via reflection on a class and sometimes on a proxy (like your problem). I hope this small example is self-explanatory.
public class ProxyTest {
interface A {
public void doit();
}
static class B implements A {
@Override
public void doit() {
System.out.println("I am a B");
}
}
static class ProxyOfA implements InvocationHandler {
private A delegate;
ProxyOfA(A delegate) {
this.delegate = delegate;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (delegate instanceof Proxy) {
//This is a proxy
InvocationHandler invocationHandler = Proxy.getInvocationHandler(delegate);
invocationHandler.invoke(delegate, method, args);
} else {
// This is not a proxy
method.invoke(delegate, args);
}
System.out.println("Proxy of Proxy invoked");
return null;
}
}
public static void main(String[] args) {
//instantiate targets
A b = new B();
A proxy = (A) Proxy.newProxyInstance(A.class.getClassLoader(), new Class[] { A.class },
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("I am a Proxy");
return null;
}
});
//instantiate proxies
A proxyOfb = (A) Proxy.newProxyInstance(A.class.getClassLoader(), new Class[] { A.class }, new ProxyOfA(b));
A proxyOfproxy = (A) Proxy.newProxyInstance(A.class.getClassLoader(), new Class[] { A.class }, new ProxyOfA(proxy));
//invoke
proxyOfb.doit();
proxyOfproxy.doit();
}
}
This will print
I am a B Proxy of Proxy invoked I am a Proxy Proxy of Proxy invoked
Upvotes: 1
Reputation: 533660
what happens when the instance is a proxied one, and the method is running though an invocation handler?
There is no difference. The Proxy must implement all the methods in your interface
Then the instance object Class here has not the method and I can not get it and invoke it.
The InvocationHandler does, but the Proxy does. The proxy calls the handler with the method from the interface it implements.
is there any way to invoke a method by its name on an instance without having to retrieve the method from the class first?
You shouldn't have to tried Proxy(s) any differently.
Upvotes: 0