Quelque chose de similaire à ServiceLoader dans Java 1.5?

Comment découvrir les classes à l’exécution dans le classpath qui implémente une interface définie?

ServiceLoader convient bien (je pense que je ne l’ai pas utilisé), mais j’ai besoin de le faire en Java 1.5.

Il n’y a rien dans Java 1.5 pour cela. Je l’ai mis en œuvre moi-même; ce n’est pas trop compliqué. Toutefois, lors de la mise à niveau vers Java 6, je devrais remplacer les appels de mon implémentation par des appels à ServiceLoader . J’aurais pu définir un petit pont entre l’application et le chargeur, mais je ne l’utilise que dans quelques endroits et l’emballage serait un bon candidat pour ServiceLoader.

C’est l’idée de base:

 public  Iterable load(Class ifc) throws Exception { ClassLoader ldr = Thread.currentThread().getContextClassLoader(); Enumeration e = ldr.getResources("META-INF/services/" + ifc.getName()); Collection services = new ArrayList(); while (e.hasMoreElements()) { URL url = e.nextElement(); InputStream is = url.openStream(); try { BufferedReader r = new BufferedReader(new InputStreamReader(is, "UTF-8")); while (true) { Ssortingng line = r.readLine(); if (line == null) break; int comment = line.indexOf('#'); if (comment >= 0) line = line.subssortingng(0, comment); Ssortingng name = line.sortingm(); if (name.length() == 0) continue; Class clz = Class.forName(name, true, ldr); Class impl = clz.asSubclass(ifc); Constructor ctor = impl.getConstructor(); S svc = ctor.newInstance(); services.add(svc); } } finally { is.close(); } } return services; } 

Une meilleure gestion des exceptions rest un exercice pour le lecteur. En outre, la méthode peut être paramétrée pour accepter un chargeur de classe choisi par l’appelant.

javax.imageio.spi.ServiceRegistry est l’équivalent des versions précédentes de Java. Il est disponible depuis Java 1.4.

Cela ne ressemble pas à une classe d’utilité générale, mais c’est vrai. Il est même un peu plus puissant que ServiceLoader , car il permet de contrôler l’ordre des fournisseurs renvoyés et d’accéder directement au registre.

Voir http://docs.oracle.com/javase/7/docs/api/index.html?javax/imageio/spi/ServiceRegistry.html.

ServiceLoader est assez basique et est utilisé (de manière informelle) dans le JDK depuis la version 1.3. ServiceLoader vient enfin d’en faire un citoyen de première classe. Il recherche simplement un fichier de ressources nommé pour votre interface, qui est essentiellement intégré au répertoire META-INF d’un fichier jar de bibliothèque.

Ce fichier contient le nom de la classe à charger.

Donc, vous auriez un fichier nommé:

META-INF / services / com.example.votre.interface

et à l’intérieur, il y a une seule ligne: com.votre.interfaceImpl.

Au lieu de ServiceLoader, j’aime Netbeans Lookup. Cela fonctionne avec 1.5 (et peut-être 1.4).

Hors de la boîte, il fait exactement la même chose que ServiceLoader, et son utilisation est sortingviale. Mais il offre beaucoup plus de flexibilité.

Voici un lien: http://openide.netbeans.org/lookup/

Voici un article sur ServiceLoader, mais il mentionne Netbeans Lookup en bas: http://weblogs.java.net/blog/timboudreau/archive/2008/08/simple_dependen.html

C’est une vieille question, mais l’autre option consiste à utiliser des annotations au niveau du package . Voir ma réponse à: Trouver des classes Java implémentant une interface

Les annotations au niveau du package sont des annotations qui se trouvent dans les classes package-info.java.

JAXB l’utilise au lieu de Service Loaders. Je pense aussi que c’est plus flexible que le chargeur de service.

Malheureusement,

Il n’y a rien dans Java 1.5 pour cette …

n’est qu’une partie de la vérité.

Il existe des services sun.misc.Service non standard sun.misc.Service environs.

http://www.docjar.com/docs/api/sun/misc/Service.html

Attention, cela ne fait pas partie de l’API J2SE standard! C’est une partie non standard du JDK de Sun. Vous ne pouvez donc pas vous y fier si vous utilisez, par exemple, JRockit .

Il n’y a aucun moyen fiable de savoir quelles classes sont dans le classpath. Selon sa documentation , ServiceLoader s’appuie sur des fichiers externes pour lui indiquer les classes à charger. Vous voudrez peut-être faire la même chose. L’idée de base est d’avoir un fichier avec le nom de la classe à charger, puis d’utiliser la reflection pour l’instancier.

Avez-vous pensé à utiliser un framework OSGI?