问题 是否有更有效的方法来获得带注释的方法?


我开始了“为了好玩,没有人知道,没人关心”的开源项目(LINKSET)。

在一个地方,我需要获得一个类的注释方法。

有没有比这更有效的方法呢?我的意思是不需要遍历每个方法?

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

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

11514
2018-02-10 14:02


起源

如果您只想知道方法是否具有注释,并且不关心可以调用的注释的内容 method.isAnnotationPresent(HandlerMethod.class) - Geoff Reedy


答案:


看看吧 思考 (依赖关系: 番石榴 和 了Javassist)。这是一个已经优化了大部分内容的库。有一个 Reflections#getMethodsAnnotatedWith() 适合您的功能要求。

这是一个 SSCCE,只是复制'n'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);
    }

}

12
2018-02-10 15:08





如果您要为每个类进行多次调用,您可以创建一个类似于类的描述符,它只会缓存此类信息。然后,当您想要检索信息时,您只需查看它的描述符。

回答你的问题:

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

将返回类的所有注释。你所做的只会返回方法的第一个注释。同样聪明:

Annotion[] annos = myMethod.getAnnotations();

返回给定方法的所有注释。


1
2018-02-10 14:11



这不会只返回类级别的annotarions吗?方法不包括在内,他对它们感兴趣 - Bozho
他们已经被缓存了 Method 对象 - 它使用的是Map - Bozho
是的但你必须在每次需要时使用反射。我所说的是一次到达那张地图,再也没有经历过反思。 - wheaties


不,但这根本不是低效率的。

例如,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) (如问题下面的评论中所示)


1
2018-02-10 14:05



那么它就像O(m *(1 + a)),其中m =方法的数量,a =每个方法的平均注释数。 a通常接近0,所以它实际上是O(m)。如果经常调用此代码,那么像O(log(m))这样的东西会更好。 - Łukasz Bownik
和 m 很少超过10;) - Bozho
嗯 - 好点:) - Łukasz Bownik
我不会指出Spring作为效率的一个例子 - 看看在Spring调用的方法中抛出异常时生成的堆栈跟踪?对于每个“真正的”方法调用,它必须通过六个级别的spring方法。幸运的是java总体来说速度非常快,并且它看起来不会导致问题,但是我想在弹簧紧密循环实例化的对象上调用方法之前要考虑两次.... - Bill K