Как найти первый метод объявления для ссылочного метода - PullRequest
2 голосов
/ 10 мая 2010

Предположим, у вас есть универсальный интерфейс и реализация:

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 набирает MyInterface до Bar. Так что, если бы я мог создать некое «типизированное представление» на MyImplementation, мой математический алгоритм мог бы сработать на самом деле.

Дополнительная информация:

Я создаю прокси для MyExtendedInterface следующим образом:

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

Перехватчик в значительной степени сканирует методы и выполняет запросы JPA для всех методов, объявленных в MyExtendedInterface, но перенаправляет все вызовы методов методов, объявленных в 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 () - это определить метод, который первоначально объявил вызываемый , и вызвать его на цели вручную.

Ответы [ 2 ]

1 голос
/ 13 мая 2010

Хорошо, вот решение, которое я придумала: поскольку я знаю базовый класс и его обобщенную структуру (что в данном случае означает T), а также MyExtendedInterface типы MyInterface - Bar я могу сканировать базовый класс реализация возможных совпадений выглядит следующим образом (псевдокод):

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

Мне не нужно универсальное решение в этом случае, так что, похоже, оно работает.

0 голосов
/ 10 мая 2010

Весь сценарий кажется странным. Вы не можете применить AOP, объявленный MyExtendedInterface к MyImplementation, потому что он не реализует его.

Во-вторых, я не понимаю, почему имеет значение, какой интерфейс определяет метод, поскольку именно эта реализация вызывается методом.

Кроме того, вы можете получить все методы, объявленные определенным классом / интерфейсом, getDeclaredMethods(). Затем вы можете итерировать их и найти то, что соответствует вашим критериям (имя)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...