theol.zacharopoulos
theol.zacharopoulos

Reputation: 49

Java dynamically invoke method which is dynamically attached (by dynamic proxy) on an object

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

Answers (2)

user3046582
user3046582

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

Peter Lawrey
Peter Lawrey

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

Related Questions