【问题标题】:How to find the first declaring method for a reference method如何找到引用方法的第一个声明方法
【发布时间】:2010-05-10 17:31:46
【问题描述】:

假设你有一个通用接口和一个实现:

public interface MyInterface<T> {

  void foo(T param);
}

public class MyImplementation<T> implements MyInterface<T> {

  void foo(T param) {

  }
}

这两种类型是我提供的框架类型。在下一步中,我希望允许用户扩展该接口以及重新声明 foo(T param) 以可能为其配备更多注释。

public interface MyExtendedInterface extends MyInterface<Bar> {

  @Override
  void foo(Bar param);

  // Further declared methods
}

我为扩展接口创建了一个 AOP 代理,并特别拦截了对进一步声明的方法的调用。由于foo(…) 现在在MyExtendedInterface 中重新声明,我无法通过简单地调用MethodInvocation.proceed() 作为MyImplementation 的实例来执行它,只实现MyInterface.foo(…) 而不是MyExtendedInterface.foo(…)

那么有没有办法访问最初声明方法的方法?关于这个例子,有没有办法找出 foo(Bar param) 最初在 MyInterface 中声明并访问相应的 Method 实例?

我已经尝试扫描基类方法以按名称和参数类型进行匹配,但这不起作用,因为泛型弹出并且MyImplementation.getMethod("foo", Bar.class) 显然会抛出NoSuchMethodException。我已经知道 MyExtendedInterface 类型 MyInterfaceBar。因此,如果我可以在 MyImplementation 上创建某种“类型化视图”,我的数学算法实际上可以运行。

附加信息:

我为MyExtendedInterface 创建代理如下:

ProxyFactory factory = new ProxyFactory();
factory.setTarget(new MyImplementation());
factory.setInterfaces(new Class[] { MyExtendedInterface.class });
factory.addInterceptor(new MyInterceptor(MyExtendedInterface.class));

拦截器几乎会扫描方法并对MyExtendedInterface 中声明的所有方法执行JPA 查询,但会将MyInterface 中声明的方法的所有方法调用路由到代理目标。只要来自 MyInterface 的方法没有被重新声明为目标然后不再实现它,这就会起作用。

public class MyInterceptor implements MethodInterceptor {

  public Object invoke(final MethodInvocation invocation)
            throws Throwable {

    // handling of query methods
    // else

    invocation.proceed();
    // ^^ works if not redeclared but not if
  }
}

所以我想做的不是 invocation.proceed() 而是检测最初声明被调用的方法并在目标上手动调用它。

【问题讨论】:

  • 我没有回应,但我认为 MyExtendedInterface.class.getMethod("foo", Bar.class) 应该没问题,带有合成或桥标记。这对你有帮助吗?
  • 我真的不明白这会有什么帮助。我遍历MyExtendedInterface 的声明方法。问题是我无法将它们与 `MyImplementation 中声明的完全匹配。
  • 你用什么做代理?程序员?公共代理?
  • 这是来自 Spring AOP,所以简单来说就是 JDK 动态代理...

标签: java generics reflection inheritance proxy


【解决方案1】:

好的,这是我想出的解决方案:据我所知,基类及其泛型结构(在这种情况下 T 意味着什么)以及 MyExtendedInterface 类型 MyInterfaceBar 我可以扫描基类可能匹配的实现如下(伪代码):

for all methods {

   skip those with non matching name and parameters length;

   for all generic parametertypes {

     if typename = T then concrete type has to be Bar
     ...
   }
}

在这种情况下,我不需要通用解决方案,所以这似乎可行。

【讨论】:

    【解决方案2】:

    整个场景看起来很奇怪。您不能将在MyExtendedInterface 上声明的 AOP 应用到MyImplementation,因为它没有实现它。

    其次,我不明白为什么哪个接口定义一个方法很重要,因为它是调用该方法的实现。

    除此之外,您还可以通过getDeclaredMethods() 获取某个类/接口声明的所有方法。然后你可以对它们进行迭代并找到符合你的条件(名称)的东西

    【讨论】:

    • 我可以。我以编程方式创建代理并添加一个简单的拦截器来拦截 every 方法调用。在这个拦截器中,我决定将实际方法调用路由到哪里。 getDeclaredMethods() 是一个选项,但我必须确保重新声明的方法实际上覆盖了 MyInterface. One could actually also declare a foo(Foobar param)` 中的一个,这不会覆盖实际的方法。所以似乎没有办法找出一个方法是否覆盖另一个方法,尤其是。涉及泛型。
    • 能否提供拦截器的代码。我不太明白你的情况。
    • 在原问题中添加了代理创建代码和拦截器。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多