Есть ли более эффективный способ получить аннотированный метод?

Я начал "для удовольствия, никто не знает, никто не заботится" о проекте с открытым исходным кодом (LinkSet).

В одном месте мне нужно получить аннотированный метод класса.

Есть ли более эффективный способ сделать это, чем это? Я имею в виду без необходимости повторения всех методов?

for (final Method method : cls.getDeclaredMethods()) {

    final HandlerMethod handler = method.getAnnotation(HandlerMethod.class);
        if (handler != null) {
                return method;
          }
        }

Ответ 1

Посмотрите Reflections (зависимости: Guava и Javassist). Это библиотека, которая уже оптимизировала большую часть всего этого. Там Reflections#getMethodsAnnotatedWith(), который соответствует вашим функциональным требованиям.

Здесь SSCCE, просто скопируйте'paste'n'run.

package com.stackoverflow;

import java.lang.reflect.Method;
import java.util.Set;

import org.reflections.Reflections;
import org.reflections.scanners.MethodAnnotationsScanner;
import org.reflections.util.ClasspathHelper;
import org.reflections.util.ConfigurationBuilder;

public class Test {

    @Deprecated
    public static void main(String[] args) {
        Reflections reflections = new Reflections(new ConfigurationBuilder()
            .setUrls(ClasspathHelper.forPackage("com.stackoverflow"))
            .setScanners(new MethodAnnotationsScanner()));
        Set<Method> methods = reflections.getMethodsAnnotatedWith(Deprecated.class);
        System.out.println(methods);
    }

}

Ответ 2

Нет. Но это совсем неэффективно.

Например, spring использует следующий код:

public static <A extends Annotation> A getAnnotation(
        Method method, Class<A> annotationType) {

    return BridgeMethodResolver.
       findBridgedMethod(method).getAnnotation(annotationType);
}

(где BridgedMethodResolver - это еще одна тема, но он просто возвращает объект Method)

Кроме того, вместо сравнения с null вы можете проверить, присутствует ли аннотация с помощью isAnnotationPresent(YourAnnotation.class) (как предложено в комментариях ниже вопроса)

Ответ 3

Если вы собираетесь сделать несколько вызовов для этого для каждого класса, вы можете создать класс дескриптора, который не делает ничего больше, чем кешировать этот тип информации. Затем, когда вы хотите получить информацию, вы просто посмотрите на ее дескриптор.

Чтобы ответить на ваш вопрос:

Class<?> _class = Whatever.class;
Annotation[] annos = _class.getAnnotations();

вернет все аннотации класса. То, что вы сделали, вернет только самую первую аннотацию метода. Как мудрый:

Annotion[] annos = myMethod.getAnnotations();

возвращает все аннотации данного метода.