Comment puis-je obtenir une liste de toutes les implémentations de l'interface par programmation en Java?
Puis-je le faire avec réflexion ou quelque chose comme ça?
- Est-il possible de le faire avec un peu de magie de l'Éclipse du raccourci ? ?
- Veuillez envisager de choisir une réponse.
Vous devez vous connecter pour publier un commentaire.
J'ai cherché pendant un moment et il semble y avoir des approches différentes, en voici un résumé:
réflexions bibliothèque est assez populaire si u n'a pas l'esprit en ajoutant de la dépendance. Il devrait ressembler à ceci:
ServiceLoader (comme par erickson réponse) et il devrait ressembler à ceci:
Notez que pour que cela fonctionne, vous devez définir
Pet
comme un ServiceProviderInterface (SPI) et de déclarer sa mise en oeuvre. vous le faire en créant un fichier dansresources/META-INF/services
avec le nomexamples.reflections.Pet
et de déclarer toutes les implémentations dePet
en ellepaquet au niveau de l'annotation. voici un exemple:
et l'annotation définition:
et vous devez déclarer le paquet au niveau de l'annotation dans un fichier nommé
package-info.java
à l'intérieur de ce paquet. voici un exemple de contenu:Noter que seuls les paquets qui sont connus pour le chargeur de classe à l'époque, sera chargé par un appel à
Package.getPackages()
.En outre, il existe d'autres approches basées sur URLClassLoader qui sera toujours limitée à des catégories qui ont été déjà chargé, Sauf si vous avez un répertoire de recherche.
Ce erickson a dit, mais si vous voulez continuer à le faire, puis prendre un coup d'oeil à Réflexions. À partir de leur page:
new Reflections("my.package").getSubTypesOf(MyInterface.class)
En général, c'est cher pour ce faire. Pour utiliser la réflexion, la classe doit être chargé. Si vous souhaitez charger chaque classe disponible dans le classpath, qui prendra du temps et de la mémoire, et n'est pas recommandé.
Si vous voulez éviter cela, vous devez mettre en place votre propre fichier de classe de l'analyseur fonctionnant de manière plus efficace, au lieu de la réflexion. Un octet code de l'ingénierie de la bibliothèque peut vous aider avec cette approche.
La Fournisseur de services de mécanisme est le classique, afin d'énumérer les implémentations d'une enfichable services. Utiliser le
ServiceLoader
dans la version 6 de Java, ou mettre en place votre propre dans les versions antérieures. Je fournis un exemple dans une autre réponse.META-INF/services/java.sql.Driver
Le printemps est une manière assez simple à réaliser ceci:
Alors vous pouvez autowire une liste de type
ITask
et le Printemps va le remplir avec toutes les implémentations:Oui, la première étape consiste à identifier les "toutes" les classes que vous vous préoccupiez. Si vous avez déjà cette information, vous pouvez énumérer par le biais de chacun d'eux et de les utiliser instanceof pour valider la relation. Un article est ici: http://www.javaworld.com/javaworld/javatips/jw-javatip113.html
Ce qu'erikson dit, c'est mieux. Voici une question connexe, et de répondre à fil - http://www.velocityreviews.com/forums/t137693-find-all-implementing-classes-in-classpath.html
Apache BCEL bibliothèque vous permet de lire des classes sans les charger. Je crois qu'il sera plus rapide parce que vous devriez être en mesure de sauter l'étape de vérification. L'autre problème avec le chargement de toutes les classes en utilisant le chargeur de classe est que vous allez souffrir d'une mémoire énorme impact, ainsi que d'exécuter, par inadvertance, de l'électricité statique de blocs de code qui vous ne voulez probablement pas à le faire.
Apache BCEL lien de la bibliothèque - http://jakarta.apache.org/bcel/
Aussi, si vous écrivez une IDE plugin (où ce que vous essayez de faire est relativement commun), l'IDE généralement vous offre des moyens plus efficaces pour accéder à la classe de la hiérarchie de l'état actuel du code de l'utilisateur.
Je suis tombé sur le même problème. Ma solution a été d'utiliser la réflexion pour examiner toutes les méthodes dans un ObjectFactory classe, en éliminant ceux qui n'ont pas été createXXX() les méthodes de retourner une instance de l'une de mes liée Pojo. Chaque classe de découverte est ajouté à une Classe tableau [], qui a ensuite été transmis à la JAXBContext l'instanciation d'appel. Cela fonctionne bien, ne demandent qu'à charger le ObjectFactory classe, qui était sur le point d'être nécessaire de toute façon. J'ai seulement besoin de maintenir la ObjectFactory classe, une tâche soit réalisée par la main (dans mon cas, car j'ai commencé avec Pojo et utilisé schemagen), ou peut être généré en tant que de besoin par xjc. De toute façon, il est performant, simple et efficace.
Essayer ClassGraph. (Avertissement, je suis l'auteur). ClassGraph prend en charge la numérisation pour les classes qui implémentent une interface donnée, soit à l'exécution ou au moment de la construction, mais aussi beaucoup plus. ClassGraph peut construire une représentation abstraite de l'ensemble de la classe graphique (toutes les classes, les annotations, les méthodes, les paramètres de la méthode, et les champs) dans la mémoire, pour toutes les classes sur le chemin de la classe, ou pour les classes dans la liste blanche des paquets, et vous pouvez interroger cette classe de graphe comme vous le souhaitez. ClassGraph prend en charge plus classpath spécification des mécanismes et des chargeurs de classes que tout autre scanner, et fonctionne parfaitement avec le nouveau JPMS module de système, donc si vous basez votre code sur ClassGraph, votre code sera au maximum de portable. Voir l'API ici.
Une nouvelle version de @kaybee99 réponse, mais maintenant de retour à ce que l'utilisateur demande: la mise en œuvre...
Le printemps est une manière assez simple à réaliser ceci:
Alors vous pouvez autowire une liste de type
ITask
et le Printemps va le remplir avec toutes les implémentations:Avec ClassGraph c'est assez simple:
Groovy code pour trouver des implémentations de
my.package.MyInterface
: