Ich habe eine Funktionalität, die ich einem Kunden für ein Software-Modell bereitstellen möchte, das wir gerade vorbereiten - und ich möchte wissen, ob es
ist Ich möchte, dass der Kunde in der Lage ist, eine Java-Klasse zu schreiben, die meine Computable
-Schnittstelle implementiert und sie in einen vorgegebenen Ordner steckt. Dieser Ordner enthält die .java-Dateien anstelle von .class-Dateien. Zur Laufzeit möchte ich, dass mein Programm diesen Ordner durchsucht und alle Computables
aus diesem Ordner extrahiert und sie in einer Map vom Namen des Computable
zum Computable
-Objekt speichert. Das Computable
sollte nur einen Standardkonstruktor haben und das It-Interface wird nur eine Methode namens compute
haben, die ein Array von Object
auf ein Object
abbildet.
Die Java Compiler-API wurde eingeführt in Java sollte SE 6 Ihnen geben, was Sie brauchen.
Sie finden Google Reflections hilfreich, um Klassen zu finden, die eine bestimmte Schnittstelle / Oberklasse im Klassenpfad implementieren / erweitern. Es ist dann so einfach wie
%Vor% Um zu testen, ob es tatsächlich einen no-arg-Standardkonstruktor gibt, prüfen Sie einfach, ob Class#newInstance()
löst keine Ausnahme aus.
Es gibt mehrere Vorschläge, die als Antworten auf diese Frage
Auch hier On-the-fly, speicherinterne Java-Code-Kompilierung für Java 5 und Java 6
Wenn es einfach ist, zur Laufzeit zu kompilieren, wäre das in Ordnung.
Sie können javax.tools
Eine Einschränkung: Die Verwendung des Compilers erzeugt eine Abhängigkeit vom JDK; Die JRE allein reicht nicht aus.
werfen Sie einen Blick darauf: Finden Sie Java-Klassen, die eine Schnittstelle implementieren
>Ich denke das wäre einfacher, wenn Sie Ihren Kunden erlauben würden, eine Code-Deklaration mit Groovy einzugeben, die Java-isch genug ist und zur Laufzeit aus einem String-Wert einfach auszuführen ist.
Es ist einfach genug, die Liste der Dateien in einem Ordner zu durchlaufen. Jemand erwähnte, dass es möglich ist, den Java-Compiler von Java aus aufzurufen (wenn Sie das JDK neu verteilen, was meiner Meinung nach ein Punkt ist, dessen Rechtmäßigkeit geprüft werden muss!). Das ist ein großer Teil des Kampfes.
Sie scheinen ein festgelegtes Modell im Kopf zu haben, bei dem nur Dateien aus dem Ordner extrahiert werden, die eine bestimmte Schnittstelle erfüllen. Ich denke, das ist, wo Ihre Methode ein wenig geben muss. Der vernünftige Weg (IMO) wäre, alle Dateien in diesem Ordner zu kompilieren, und dann, wenn ihre Klassen irgendwo versteckt sind, können Sie sie laden und reflektieren und dann bestimmen, welche von ihnen "tun" die Schnittstelle und welche nicht. Jene, die das nicht tun, werden unnötigerweise in Ihre JVM geladen, aber wenn es nicht absichtlich sehr platzverschwenderisch ist, kann Code, den Sie nicht ausführen, Ihrem Programm nicht schaden.
Nachdem Sie bestimmt haben, welche die berechenbare Sache machen, können Sie diese Klassen (oder Instanzen davon) in einer Sammlung speichern und tun, was Sie wollen. Sie ignorieren einfach die anderen.
Sie könnten BeanShell verwenden. Diese Bibliothek ist klein und benötigt kein JDK. Es wird in einer Reihe von IDE- und Webservern verwendet. Die neueste Version scheint die Unterstützung zu haben, die Sie benötigen, um .java-Dateien aus dem Klassenpfad zu laden. (Noch in der Beta)
Tags und Links java