Quelle est la meilleure façon de rechercher le chemin de classe entier pour une classe annotée?
Je fais une bibliothèque et je veux permettre aux utilisateurs d'annoter leurs classes, donc lorsque l'application Web démarre, je dois analyser le chemin de classe entier pour une certaine annotation.
Connaissez-vous une bibliothèque ou une installation Java pour ce faire?
Edit: je pense à quelque chose comme la nouvelle fonctionnalité pour Java EE 5 Web Services ou EJB. Vous annotez votre classe avec @WebService
ou @EJB
et le système trouve ces classes lors du chargement afin qu'elles soient accessibles à distance.
la source
@Conditional
annotations. Donc, si une classe a sa@Conditional
valeur renvoyant false, elle ne sera pas renvoyée parfindCandidateComponents
, même si elle correspondait au filtre du scanner. Cela m'a jeté aujourd'hui - j'ai fini par utiliser la solution de Jonathan ci-dessous à la place.BeanDefinition
objet ne fournit pas un moyen d'obtenir directement la classe. La chose la plus proche semble être cellegetBeanClassName
qui renvoie un nom de classe complet, mais le comportement exact de cette méthode n'est pas clair. De plus, il n'est pas clair dans quel chargeur de classe la classe a été trouvée.Class<?> cl = Class.forName(beanDef.getBeanClassName());
farenda.com/spring/find-annotated-classesEt une autre solution est les réflexions de Google .
Examen rapide:
la source
new Reflections("my.package").getTypesAnnotatedWith(MyAnnotation.class)
. c'est tout.Vous pouvez trouver des classes avec n'importe quelle annotation donnée avec ClassGraph , ainsi que rechercher d'autres critères d'intérêt, par exemple les classes qui implémentent une interface donnée. (Avertissement, je suis l'auteur de ClassGraph.) ClassGraph peut construire une représentation abstraite du graphique de classe entier (toutes les classes, annotations, méthodes, paramètres de méthode et champs) en mémoire, pour toutes les classes sur le chemin de classe, ou pour les classes dans des packages sur liste blanche, et vous pouvez interroger ce graphique de classe comme vous le souhaitez. ClassGraph prend en charge plus de mécanismes de spécification de chemin de classe et de chargeurs de classe que tout autre scanner, et fonctionne également de manière transparente avec le nouveau système de module JPMS, donc si vous basez votre code sur ClassGraph, votre code sera au maximum portable. Voir l'API ici.
la source
Reflections
. De plus, si vous utilisez goyave / etc et que vous souhaitez changer les collections, c'est facile comme bonjour. Grands commentaires à l'intérieur aussi.Si vous voulez un poids vraiment léger (pas de dépendances, API simple, fichier jar de 15 Ko) et une solution très rapide , jetez un œil
annotation-detector
à https://github.com/rmuller/infomas-aslAvertissement: je suis l'auteur.
la source
Vous pouvez utiliser l'API Java Pluggable Annotation Processing pour écrire un processeur d'annotations qui sera exécuté pendant le processus de compilation et collectera toutes les classes annotées et construira le fichier d'index pour une utilisation à l'exécution.
C'est le moyen le plus rapide possible de faire la découverte de classe annotée car vous n'avez pas besoin d'analyser votre chemin de classe au moment de l'exécution, ce qui est généralement une opération très lente. Cette approche fonctionne également avec n'importe quel chargeur de classe et pas seulement avec les URLClassLoaders généralement pris en charge par les scanners d'exécution.
Le mécanisme ci-dessus est déjà implémenté dans la bibliothèque ClassIndex .
Pour l'utiliser, annotez votre annotation personnalisée avec la méta-annotation @IndexAnnotated . Cela créera au moment de la compilation un fichier d'index: META-INF / annotations / com / test / YourCustomAnnotation répertoriant toutes les classes annotées. Vous pouvez accéder à l'index lors de l'exécution en exécutant:
la source
Est-il trop tard pour répondre. Je dirais qu'il vaut mieux utiliser des bibliothèques comme ClassPathScanningCandidateComponentProvider ou des scannotations
Mais même après que quelqu'un veuille l'essayer avec classLoader, j'en ai écrit moi-même pour imprimer les annotations des classes dans un package:
Et dans config File, vous mettez le nom du paquet et le démasquez dans une classe.
la source
Avec Spring, vous pouvez également simplement écrire ce qui suit en utilisant la classe AnnotationUtils. c'est à dire:
Pour plus de détails et toutes les différentes méthodes, consultez les documents officiels: https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/core/annotation/AnnotationUtils.html
la source
null
valeur comme deuxième paramètre (qui définit la classe, dans laquelle la hiérarchie d'héritage Spring va rechercher une classe qui utilise l'annotation), vous obtiendrez toujours unnull
retour, selon l'implémentation.Il y a un merveilleux commentaire de zapp qui coule dans toutes ces réponses:
la source
L'API Classloader n'a pas de méthode "énumérer", car le chargement de classe est une activité "à la demande" - vous avez généralement des milliers de classes dans votre chemin de classe, dont seulement une fraction sera jamais nécessaire (le rt.jar seul est de 48 Mo de nos jours!).
Donc, même si vous pouviez énumérer toutes les classes, cela prendrait beaucoup de temps et de mémoire.
L'approche simple consiste à répertorier les classes concernées dans un fichier d'installation (xml ou tout ce qui vous convient); si vous voulez le faire automatiquement, limitez-vous à un répertoire JAR ou à un répertoire de classe.
la source
Google Reflection si vous souhaitez également découvrir des interfaces.
Spring
ClassPathScanningCandidateComponentProvider
ne découvre pas les interfaces.la source
Google Reflections semble être beaucoup plus rapide que Spring. Trouvé cette demande de fonctionnalité qui résout cette différence: http://www.opensaga.org/jira/browse/OS-738
C'est une raison pour utiliser Reflections car le temps de démarrage de mon application est vraiment important pendant le développement. Les réflexions semblent également très faciles à utiliser pour mon cas d'utilisation (trouver tous les implémenteurs d'une interface).
la source
Si vous cherchez une alternative aux réflexions, je voudrais recommander Panda Utilities - AnnotationsScanner . C'est un scanner sans Guava (Guava a ~ 3 Mo, Panda Utilities a ~ 200 Ko) basé sur le code source de la bibliothèque de réflexions.
Il est également dédié aux recherches futures. Si vous souhaitez analyser plusieurs fois les sources incluses ou même fournir une API, qui permet à quelqu'un d'analyser le chemin de classe actuel, les
AnnotationsScannerProcess
caches sont tous récupérésClassFiles
, donc c'est très rapide.Exemple simple d'
AnnotationsScanner
utilisation:la source
Le printemps a quelque chose appelé une
AnnotatedTypeScanner
classe.Cette classe utilise en interne
Cette classe a le code pour l'analyse réelle des ressources classpath . Pour ce faire, il utilise les métadonnées de classe disponibles au moment de l'exécution.
On peut simplement étendre cette classe ou utiliser la même classe pour la numérisation. Voici la définition du constructeur.
la source