Java - getting the signature of a method in an interface, and the same for its Proxy implementation
I'm looking for a way to extract the essence of a signature in Java. The reason is that I want to use the signature as a unique key in a 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 false.
This code is not the code I'll use, because I need it inside the InvocationHandler, but I'm wondering if regarding the Proxy implementations and the interface, getting method.getName()
and method.getParameterTypes()
is enough or I should use meth开发者_StackOverflow社区od.getTypeParameters()
and method.getParameterAnnotations()
as well?
In short: how to get a method signature that is the same for an interface and its java.lang.reflect.Proxy implementations?
I think you want the Method
passed in the 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");
}
}
What about using the result of Method.toGenericString
as the key? The string it returns includes all details of the signature, as far as I can tell.
Another thing that might be useful is: Method m2 = i.getClass().getMethod("compute", String.class).getDeclaringClass().getMethod("compute", String.class);
. That might result in m1.equals(m2)
returning true.
I just had a bug with code doing this, I took name, genericReturnType and genericParameterTypes, and I had problems when working with proxies because I lost the generic information.
I switched to use name, returnType and parameterTypes and it works fine...
I also considered using declaringClass but I removed it and don't remember exactly how I did this...
精彩评论