2010-12-21 4 views
5

Es scheint, als ob jeder einen unangenehmen Pinsel mit der Java Service Provider hatte, die Sie mit einer Datei namens META-INF/services/com.example.Interface machen können, die aber niemand benutzt, außer dem Versuch, den richtigen XML-Parser zu laden . Ich versuche, mit einer Bibliothek zu arbeiten, die die Dienstanbieter-API verwendet, und es zu überlisten, so dass ich einige Klassen mit Laufzeitverlängerung (mit cglib) bereitstellen kann, die die Schnittstelle nicht wirklich implementieren, aber dafür leicht gemacht werden können.Wie soll die Java Service Provide API funktionieren?

Grundsätzlich denke ich, dass die Schritte, die ich durchführen müssen, sind:

  1. einen Lader benutzerdefinierte Klasse erstellen, die auf GetResources reagieren (...) und geben eine „extra“ URL
  2. haben Sie auch, dass Klassenladehaken getResourceAsStream (...) eine Liste der Klassen kehre ich mit cglib manipulieren werde, wenn sie für die „extra“ Ressource Schließlich
  3. gefragt haben, dass Klassenlader diese Klassen laden, wenn

angefordert Aber Hier verschwinde ich. Wenn die Bibliothek beispielsweise versucht herauszufinden, welche Implementierer da draußen sind, ruft sie getResources (...) auf, die eine Menge URLs zurückgibt. Aber getResourceAsStream (...) nimmt keine URLs, es braucht "Namen". Namen, die klassenpfadrelativ zu sein scheinen und deshalb überall gleich sind. Also hat META-INF/services/com.example.Interface in den gleichen "Namen" wie META-INF/services/com.example.Interface in ihrer JAR, oder? Außer irgendwie funktioniert das mit diesen gesprengten XML-Parsern ...

Natürlich setzt alles davon voraus, dass sie intelligent/freundlich genug waren, um ClassLoader.getSystemClassLoader() anstatt ClassLoader.getSystemResources (...), ClassLoader, aufzurufen. getSystemResourceAsStream (...), etc., da es im letzteren Fall keine Möglichkeit gibt, den ClassLoader anzuhängen und die gefälschte Datei bereitzustellen.

Ich denke, in diesem Fall könnte ich BCEL verwenden, um die Klassendateien zu manipulieren, wenn mein Code von Maven verpackt wird, anstatt zu warten, bis es mit cglib läuft?

+0

Konnten Sie einige Stubs kompilieren und sie über META-INF/services auf die übliche Weise registrieren, aber dann proxy sie mit cglib, sobald sie geladen sind? – OrangeDog

+0

Was ist die eigentliche Frage/Problem? Ihr Ansatz, einen benutzerdefinierten Klassenlader zu verwenden (und ihn als Kontextklassenlader um den Aufruf der Bibliothek festzulegen, die getResources aufruft ...) sollte funktionieren. –

+0

bkail - Das ultimative Problem ist, dass ich Klassen ('Type1',' Type2', ...) habe, die von einer anderen Klasse ('Runner') ausgeführt werden können, die selbst in einer GUI laufen. Aus verschiedenen Gründen ist das in meiner Anwendung hässlich. Was ich tun möchte, ist, sie dynamisch zu "fusionieren" und "Runner $ Type1", "Runner $ Type2" usw. der GUI zu präsentieren, so dass die Benutzer wissen, welche Klassen verfügbar sind. –

Antwort

3

Die Idee, die ich beschrieben habe, war auf dem richtigen Weg. Der Fehler, den ich gemacht habe, war zu denken, dass ich ClassLoader.getResourceAsStream(..) verwende, um auf den Inhalt der URLs zuzugreifen. Stattdessen sollten Sie nur URL.openStream().

Hätte ich es vor dem Posten gefunden, bietet java.util.ServiceLoader (@since 1.6) einige Einblicke, wie man Dinge richtig macht.

Verwandte Themen