Wie kann der gesamte Klassenpfad am besten nach einer mit Anmerkungen versehenen Klasse durchsucht werden?
Ich mache eine Bibliothek und möchte den Benutzern erlauben, ihre Klassen mit Anmerkungen zu versehen. Wenn die Webanwendung gestartet wird, muss ich den gesamten Klassenpfad nach bestimmten Anmerkungen durchsuchen.
Kennen Sie eine Bibliothek oder eine Java-Einrichtung, um dies zu tun?
Bearbeiten: Ich denke über so etwas wie die neue Funktionalität für Java EE 5 Web Services oder EJBs nach. Sie kommentieren Ihre Klasse mit @WebService
oder @EJB
und das System findet diese Klassen beim Laden, sodass auf sie remote zugegriffen werden kann.
quelle
@Conditional
Anmerkungen auswerten und handeln . Wenn der@Conditional
Wert einer Klasse also false zurückgibt, wird er nicht zurückgegebenfindCandidateComponents
, selbst wenn er mit dem Filter des Scanners übereinstimmt. Das hat mich heute umgehauen - ich habe stattdessen Jonathans Lösung unten verwendet.BeanDefinition
Objekt keine Möglichkeit bietet, die Klasse direkt abzurufen. Das Nächste scheint zu sein,getBeanClassName
das einen vollständig qualifizierten Klassennamen zurückgibt, aber das genaue Verhalten dieser Methode ist nicht klar. Es ist auch nicht klar, in welchem Klassenlader die Klasse gefunden wurde.Class<?> cl = Class.forName(beanDef.getBeanClassName());
farenda.com/spring/find-annotated-classesEine weitere Lösung sind Google-Überlegungen .
Kurzübersicht:
quelle
new Reflections("my.package").getTypesAnnotatedWith(MyAnnotation.class)
. c'est tout.Mit ClassGraph können Sie Klassen mit einer bestimmten Anmerkung finden und nach anderen interessanten Kriterien suchen, z. B. nach Klassen, die eine bestimmte Schnittstelle implementieren. (Haftungsausschluss, ich bin der Autor von ClassGraph.) ClassGraph kann eine abstrakte Darstellung des gesamten Klassendiagramms (alle Klassen, Anmerkungen, Methoden, Methodenparameter und Felder) im Speicher, für alle Klassen im Klassenpfad oder für Klassen in erstellen Whitelist-Pakete, und Sie können dieses Klassendiagramm abfragen, wie Sie möchten. ClassGraph unterstützt mehr Klassenpfadspezifikationsmechanismen und Klassenladeprogramme als jeder andere Scanner und funktioniert auch nahtlos mit dem neuen JPMS-Modulsystem. Wenn Sie Ihren Code also auf ClassGraph basieren, ist Ihr Code maximal portabel. Siehe die API hier.
quelle
Reflections
. Auch wenn Sie Guave / etc verwenden und die Sammlungen ändern möchten, ganz einfach. Tolle Kommentare auch drinnen.Wenn Sie ein wirklich geringes Gewicht (keine Abhängigkeiten, einfache API, 15-KB-JAR-Datei) und eine sehr schnelle Lösung wünschen , besuchen
annotation-detector
Sie https://github.com/rmuller/infomas-aslHaftungsausschluss: Ich bin der Autor.
quelle
Sie können die Java Pluggable Annotation Processing API verwenden, um einen Annotationsprozessor zu schreiben, der während des Kompilierungsprozesses ausgeführt wird, alle mit Anmerkungen versehenen Klassen sammelt und die Indexdatei für die Laufzeit erstellt.
Dies ist der schnellste Weg, um annotierte Klassen zu erkennen, da Sie Ihren Klassenpfad zur Laufzeit nicht scannen müssen, was normalerweise sehr langsam ist. Dieser Ansatz funktioniert auch mit jedem Klassenladeprogramm und nicht nur mit URLClassLoadern, die normalerweise von Laufzeitscannern unterstützt werden.
Der obige Mechanismus ist bereits in ClassIndex implementiert Bibliothek .
Um es zu verwenden, kommentieren Sie Ihre benutzerdefinierte Annotation mit @IndexAnnotated Meta-Annotation. Dadurch wird zur Kompilierungszeit eine Indexdatei erstellt: META-INF / annotations / com / test / YourCustomAnnotation, in der alle mit Anmerkungen versehenen Klassen aufgelistet sind. Sie können zur Laufzeit auf den Index zugreifen, indem Sie Folgendes ausführen:
quelle
Ist es zu spät zu antworten? Ich würde sagen, es ist besser, Bibliotheken wie ClassPathScanningCandidateComponentProvider oder ähnliches zu verwenden Scannotations zu verwenden
Aber selbst nachdem jemand es mit classLoader ausprobieren möchte, habe ich einige selbst geschrieben, um die Anmerkungen von Klassen in einem Paket zu drucken:
In der Konfigurationsdatei geben Sie den Paketnamen ein und entfernen die Zuordnung zu einer Klasse.
quelle
Mit Spring können Sie auch einfach Folgendes mit der AnnotationUtils-Klasse schreiben. dh:
Weitere Informationen und alle verschiedenen Methoden finden Sie in den offiziellen Dokumenten: https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/core/annotation/AnnotationUtils.html
quelle
null
Wert als zweiten Parameter eingeben (der die Klasse definiert, in der die Vererbungshierarchie Spring nach einer Klasse sucht, die die Annotation verwendet), erhalten Sienull
je nach Implementierung immer eine Rückmeldung .Es gibt einen wunderbaren Kommentar von zapp , der in all diesen Antworten versinkt:
quelle
Die Classloader-API verfügt nicht über eine "Enumerate" -Methode, da das Laden von Klassen eine "On-Demand" -Aktivität ist. In Ihrem Klassenpfad befinden sich normalerweise Tausende von Klassen, von denen nur ein Bruchteil jemals benötigt wird (rt.jar) allein ist heutzutage 48MB!).
Also, auch wenn Sie könnten alle Klassen aufzählen , wäre dies sehr zeit- und speicherintensiv.
Der einfache Ansatz besteht darin, die betroffenen Klassen in einer Setup-Datei aufzulisten (XML oder was auch immer Ihren Vorstellungen entspricht). Wenn Sie dies automatisch tun möchten, beschränken Sie sich auf ein JAR- oder ein Klassenverzeichnis.
quelle
Google Reflection wenn Sie auch Schnittstellen entdecken möchten.
Der Frühling
ClassPathScanningCandidateComponentProvider
entdeckt keine Schnittstellen.quelle
Google Reflections scheint viel schneller zu sein als der Frühling. Es wurde diese Funktionsanforderung gefunden, die diesen Unterschied behebt: http://www.opensaga.org/jira/browse/OS-738
Dies ist ein Grund, Reflections zu verwenden, da die Startzeit meiner Anwendung während der Entwicklung sehr wichtig ist. Reflexionen scheinen auch für meinen Anwendungsfall sehr einfach zu verwenden zu sein (alle Implementierer einer Schnittstelle finden).
quelle
Wenn Sie nach einer Alternative zu Reflexionen suchen, würde ich Panda Utilities - AnnotationsScanner empfehlen . Es ist ein Guaven-freier Scanner (Guava hat ~ 3 MB, Panda Utilities hat ~ 200 KB), der auf dem Quellcode der Reflexionsbibliothek basiert.
Es ist auch für zukünftige Suchvorgänge vorgesehen. Wenn Sie mehrere eingeschlossene Quellen scannen oder sogar eine API bereitstellen möchten, mit der jemand den aktuellen Klassenpfad scannen kann, werden
AnnotationsScannerProcess
alle abgerufenen Caches zwischengespeichertClassFiles
, sodass dies sehr schnell geht.Einfaches
AnnotationsScanner
Anwendungsbeispiel:quelle
Der Frühling hat eine
AnnotatedTypeScanner
Klasse.Diese Klasse wird intern verwendet
Diese Klasse enthält den Code für das eigentliche Scannen des Klassenpfads . Dazu werden die zur Laufzeit verfügbaren Klassenmetadaten verwendet.
Man kann diese Klasse einfach erweitern oder dieselbe Klasse zum Scannen verwenden. Unten ist die Konstruktordefinition.
quelle