Java - 获取接口中方法的签名,其代理实现也是如此

发布于 2024-08-09 06:15:17 字数 947 浏览 11 评论 0原文

我正在寻找一种方法来提取 Java 中签名的本质。原因是我想使用签名作为 java.lang.reflect.Proxies 的 Map 中的唯一键。

使用这段代码:

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));
}

结果显然是错误的。

这段代码不是我将使用的代码,因为我需要它在 InvocableHandler 中,但我想知道是否关于代理实现和接口,获取 method.getName()method.getParameterTypes() 就足够了,还是我也应该使用 method.getTypeParameters()method.getParameterAnnotations()

简而言之:如何获得与接口及其 java.lang.reflect.Proxy 实现相同的方法签名?

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 method.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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

街角卖回忆 2024-08-16 06:15:17

我认为您希望将 Method 传递到 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");
    }
}

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");
    }
}
人│生佛魔见 2024-08-16 06:15:17

使用 Method.toGenericString 的结果作为键怎么样?据我所知,它返回的字符串包含签名的所有详细信息。

另一件可能有用的事情是: Method m2 = i.getClass().getMethod("compute", String.class).getDeclaringClass().getMethod("compute", String.class); 。这可能会导致 m1.equals(m2) 返回 true。

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.

单挑你×的.吻 2024-08-16 06:15:17

我只是在执行此操作时遇到了代码错误,我获取了名称、genericReturnType 和 genericParameterTypes,并且在使用代理时遇到了问题,因为我丢失了通用信息。

我改用 name、returnType 和parameterTypes,它工作得很好...

我也考虑过使用 declaringClass,但我删除了它,并且不记得我是如何做到这一点的...

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...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文