Java: Как проверить, переопределен ли метод, используя отражение - PullRequest
5 голосов
/ 12 марта 2012

Мне нужно выполнить некоторую обработку, чтобы определить зависимости аннотированных классов JSR-330, используя отражение.

Мне полностью известны все контейнеры IoC, совместимые с JSR-330, такие как Spring, Guice или PicoContainer. Однако мне нужно не разрешать и вводить зависимости, а выявлять их.

Это в основном означает, что мне нужно реализовать реализацию JSR-330, по крайней мере, когда дело доходит до рефлексивного класса "синтаксический анализ".

Есть одна часть спецификации JSR-330, которую я нахожу немного проблематичной для реализации:

Метод, аннотированный @Inject, который переопределяет другой метод аннотированный @Inject будет введен только один раз за инъекцию запрос за экземпляр. Метод без аннотации @Inject, который переопределяет метод, аннотированный @Inject, не будет внедрен.

Это означает, что подклассы могут переопределить контракт автопроводки своего базового класса, а также подключиться к потоку впрыска (посредством полиморфизма).

Вот мой вопрос: Учитывая иерархию классов, есть ли простой способ проверить, переопределяется ли метод в некоторой части иерархии дальше вниз по иерархии?

Самый простой способ сделать это в моем случае - это рекурсия с листа иерархии:

private List<Method> getInjectableMethods(final Class<?> clazz) {
    // recursive stop condition
    if(clazz == null) {
        return emptyList();
    }

    // recursively get injectable methods from superclass
    final List<Method> allInjectableMethods = newLinkedList(getInjectableMethods(clazz.getSuperclass()));
    final List<Method> injectableMethods = newArrayList();

    // any overridden method will be present in the final list only if it is injectable in clazz
    for (final Method method : clazz.getDeclaredMethods()) {
        removeIf(allInjectableMethods, Methods.Predicates.overriddenBy(method));
        if (isInjectable(method)) {
            injectableMethods.add(method);
        }
    }
    allInjectableMethods.addAll(injectableMethods);

    return allInjectableMethods;
}

Что касается переопределенного предикатом, похожим на Guava, я бы проверил, что:

  • Методы, определяющие классы, находятся в отношении isAssignableFrom
  • Имя метода совпадает
  • Методы формальных параметров одинаковы

Получившаяся сложность равна O (n ^ 2) в отношении количества методов в иерархии.

Мне было интересно, есть ли какой-нибудь более простой или эффективный способ добиться этого или какие-либо библиотеки с такой функциональностью. Я неудачно выглядел в Guava и Apache Commons ...

1 Ответ

1 голос
/ 13 марта 2012

К сожалению, граф классов доступен для навигации только в корневом направлении - поэтому нет способа найти все производные классы, кроме как проверить все классы, доступные для определенного загрузчика классов.Контейнеры IoC не имеют этой проблемы, потому что они всегда знают конкретную реализацию (это является частью конфигурации)

Деревья наследования обычно создаются средами IDE, но AFAIUK использует индексацию брайт-сил по всем доступным источникам / классам (выможете посмотреть источники сообщества editio InteliiJ IDEA для подсказок)

...