Java - getting the signature of a method in an interface and the same for its Proxy implementation

I am looking for a way to extract a signature entity in Java. The reason is because I want to use the signature as a unique key in the Map for my java.lang.reflect.Proxies.

With this code:

public interface MyInterface {
  public int compute(String s);
}

...
public static void main (String... args) throws Exception {
  InvocationHandler handler = ...;
  MyInterface i = (MyInterface) Proxy.newProxyInstance(
      Beans.class.getClassLoader(),
      new Class<?>[] { MyInterface.class },
      handler);

  Method m1 = MyInterface.class.getMethod("compute", String.class);
  Method m2 = i.getClass().getMethod("compute", String.class);
  System.out.printf("%b%f", m1.equals(m2));
}

      

The result is obviously wrong.

This code is not the code I will be using because I need it inside the InvocationHandler, but I am wondering if, regarding the implementation of the proxy and interface, is getting method.getName()

and method.getParameterTypes()

enough or should I use method.getTypeParameters()

and method.getParameterAnnotations()

?

In short: how to get a method signature that is the same for the interface and its java.lang.reflect.Proxy implementations?

+2


source to share


3 answers


I think you want to Method

go to InvocationHandler

.



package playtest;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;

import org.junit.Test;
import static junit.framework.Assert.*;

interface MyInterface {
    void run();
    void about();
    void run(String j);
}


public class TestProxyClass {
    @Test
    public void testDeclaringClass() throws Exception {
        final Map<Method, Runnable> actions = new HashMap<Method, Runnable>();

        actions.put(MyInterface.class.getMethod("run"), new Runnable() {

            @Override
            public void run() {
                System.out.println("run");
            }

        } );
        actions.put(MyInterface.class.getMethod("run", String.class), new Runnable() {

            @Override
            public void run() {
                System.out.println("run string");
            }

        } );
        actions.put(MyInterface.class.getMethod("about"), new Runnable() {

            @Override
            public void run() {
                System.out.println("about");
            }

        } );

        MyInterface face = (MyInterface) Proxy.newProxyInstance(getClass().getClassLoader(), 
                new Class<?>[] { MyInterface.class }, new InvocationHandler() {

                    @Override
                    public Object invoke(Object proxy, Method method,
                            Object[] args) throws Throwable {
                        actions.get(method).run();
                        return null;
                    }

                } );

        face.run();
        face.about();
        face.run("Hello");
    }
}

      

+3


source


How to use the result Method.toGenericString

as a key? As far as I know, the returned string includes all the details of the signature.



Another useful thing Method m2 = i.getClass().getMethod("compute", String.class).getDeclaringClass().getMethod("compute", String.class);

. This can cause it to m1.equals(m2)

return true.

+1


source


I just had an error with the code doing this, I took the name, genericReturnType and genericParameterTypes, and I had problems working with the proxy because I lost general information.

I switched to using name, returnType and parameterTypes and it works great ...

I also considered using declaringClass, but I removed it and don't remember exactly how I did it ...

0


source







All Articles