2010-02-10 4 views
10

Ich begann ein Open-Source-Projekt "für Spaß, niemand weiß, niemand kümmert sich" (LinkSet).Gibt es eine effizientere Methode, um eine annotierte Methode zu erhalten?

An einer Stelle muss ich eine annotierte Methode einer Klasse bekommen.

Gibt es einen effizienteren Weg, dies zu tun? Ich meine, ohne die Notwendigkeit, jede Methode zu durchlaufen?

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

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

Wenn Sie nur, wenn die Methode die Anmerkung muss wissen wollen und sie über den Inhalt der Anmerkung nicht kümmern Sie 'method.isAnnotationPresent (HandlerMethod.class) nennen kann' –

Antwort

1

Nein. Aber das ist überhaupt nicht ineffizient.

Zum Beispiel Feder ist mit dem folgenden Code:

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

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

(wo die BridgedMethodResolver ein anderes Thema, aber es gibt nur ein Method Objekt)

Auch anstelle von null zu vergleichen, können Sie Überprüfen Sie, ob eine Anmerkung mit isAnnotationPresent(YourAnnotation.class) vorhanden ist (wie in den Kommentaren unter der Frage vorgeschlagen)

+0

Nun, es ist so etwas wie O (m * (1 + a)) wobei m = Anzahl der Methoden und a = durchschnittliche Anzahl der Annotationen pro Methode. a ist oft nahe bei 0, also ist es eigentlich O (m). Etwas wie O (log (m)) wäre besser, wenn dieser Code oft aufgerufen wird. –

+0

und 'm' ist selten mehr als 10;) – Bozho

+0

hmm - guter Punkt :) –

1

Wenn Sie mehrere Aufrufe für jede Klasse aufrufen werden Sie können eine Deskriptor-ähnliche Klasse erstellen, die nur diese Art von Information zwischenspeichert. Wenn Sie dann die Informationen abrufen möchten, sehen Sie sich den Deskriptor an.

Um Ihre Frage zu beantworten:

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

werden alle Anmerkungen einer Klasse zurück. Was Sie getan haben, gibt nur die allererste Annotation einer Methode zurück. Gleichermaßen:

Annotion[] annos = myMethod.getAnnotations(); 

gibt alle Anmerkungen einer bestimmten Methode zurück.

+0

wird dies nicht nur Annotarions auf Klassenebene zurückgeben ? die Methoden werden nicht enthalten sein, und er interessiert sich für sie – Bozho

+0

sie sind bereits im 'Method' Objekt zwischengespeichert - es verwendet eine Karte – Bozho

+0

Ja, aber Sie müssen Reflexion jedes Mal verwenden, wenn Sie sie wollen.Was ich sagen will, ist, einmal auf diese Karte zu kommen und nie wieder durch die Reflexion zu gehen. – wheaties

12

Schauen Sie nach Reflections (Abhängigkeiten: Guava und Javassist). Es ist eine Bibliothek, die das meiste schon optimiert hat. Es gibt eine Reflections#getMethodsAnnotatedWith(), die Ihren funktionellen Anforderungen entspricht.

Hier ist ein SSCCE, nur copy'n'paste'n'run es.

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); 
    } 

} 
Verwandte Themen