Ich versuche, den besten Weg zum Erstellen einer neuen Instanz einer Klasse zu ermitteln, basierend darauf, welche Klassen zur Laufzeit auf dem Klassenpfad verfügbar sind.Erstellen Sie die Implementierung der Java-Klasse dynamisch basierend auf bereitgestellten Abhängigkeiten zur Laufzeit
Zum Beispiel habe ich eine Bibliothek, die eine JSON-Antwort in mehreren Klassen analysiert werden muss. Die Bibliothek verfügt über folgende Schnittstelle:
JsonParser.java
:
public interface JsonParser {
<T> T fromJson(String json, Class<T> type);
<T> String toJson(T object);
}
Diese Klasse hat mehrere Implementierungen, dh GsonJsonParser
, JacksonJsonParser
, Jackson2JsonParser
, und zur Zeit wird der Benutzer der Bibliothek erforderlich „Pick“ ihre Umsetzung zu basierend darauf verwendet werden, welche Bibliothek sie in ihr Projekt aufgenommen haben. Zum Beispiel:
JsonParser parser = new GsonJsonParser();
SomeService service = new SomeService(parser);
Was würde Ich mag zu tun, wird dynamisch abholen, welche Bibliothek auf dem Classpath ist, und die richtige Instanz erstellen, so dass der Benutzer der Bibliothek, nicht daran zu denken, hat (oder müssen sogar wissen, die interne Implementierung einer anderen Klasse JSON analysiert).
Ich erwäge etwas Ähnliches wie die folgenden:
try {
Class.forName("com.google.gson.Gson");
return new GsonJsonParser();
} catch (ClassNotFoundException e) {
// Gson isn't on classpath, try next implementation
}
try {
Class.forName("com.fasterxml.jackson.databind.ObjectMapper");
return new Jackson2JsonParser();
} catch (ClassNotFoundException e) {
// Jackson 2 was not found, try next implementation
}
// repeated for all implementations
throw new IllegalStateException("You must include either Gson or Jackson on your classpath to utilize this library");
dies eine geeignete Lösung sein würde? Es scheint ein bisschen wie ein Hack zu sein, und nutzt Ausnahmen, um den Fluss zu kontrollieren.
Gibt es einen besseren Weg, dies zu tun?
Ich stimme zu, es ist ein * hack *. Wählen Sie eine JSON-Parser-Abhängigkeit aus und verwenden Sie sie? Ihr Ansatz könnte auch * unerwartet * nicht deterministisch ** werden; abhängig von den JARs (und möglicherweise der Reihenfolge der JARs im Klassenpfad) könnte sich das Programmverhalten ändern. –
@ElliottFrisch Ich möchte das machen, aber zur Zeit haben die Anwendungen, die dies verwenden, einen dieser Parser, und ich versuche zu vermeiden, dass eine zweite Abhängigkeit entsteht, wenn sie anders ist als die, die ich gewählt habe zu verpacken (oder dieselbe Bibliothek, andere Version). – Casey
@ElliottFrisch Es scheint, es ist nicht so ein Hack, siehe meine Antwort, wo ich Link zu Spring's Umsetzung des gleichen Problems gab. – Andremoniy