Hallo!
In letzter Zeit wollte ich bischen mehr über modulares Programmieren lernen, also hab ich mal gegoogled wie das denn so aussieht wenn man Plugins bei Laufzeit in sein Programm laden möchte.
Mein Szenario ist folgendes:
Ich habe ein Programm welches ueber TCP eine Verbindung zu einem Server herstellt (IRC Bot).
Nun kriegt das Programm laufend Nachrichten vom Server. Bei bestimmten Nachrichten/Triggern,
zB. wenn ein bestimmter Nutzer im Chat was schreibt, soll der Bot etwas bestimmtes machen.
Funktioniert alles einwandfrei.
Was ich mir nun überlegt habe:
Ok, jetzt will ich aber bei Laufzeit Plugins laden, die dann bei bestimmten Triggern etwas bestimmtes tun. Nehmen wir an ich schreibe ein Plugin my.domain.irc.bot.plugins.HeiseNews. Dieses Plugin (wird mit allen anderen geladenen Plugins) in einer ArrayList<PluginInterface> gespeichert, welches Instanzvariable der Klasse Bot ist.
Kommt jetzt wieder von einem Nutzer ein Befehl (der Nutzer schreibt dazu im Chat zB: !news), laufe ich die ArrayList<PluginInterface> durch und rufe in jedem Plugin eine Methode "messageEvent()" auf, die ggf. auch bestimmte Übergabeparameter beinhaltet (wie zB. sourceNick, derjenige der !news getriggert hat).
Jetzt zu meiner ersten Frage: Ist die Denkweise wie ich da ran geh in Ordnung oder kann ich mir viel Arbeit und Mühe mit einer anderen Methode, das umzusetzen, ersparen?
Zweite Frage(n):
1. Hat eventuell jemand ein schönes Beispiel bei dem Plugins in ein Test-Programm geladen werden? (Sollte leicht verständlich/nicht allzuviel Code sein, hab bisher nur Riesen-Projekte mit einem Interface für Plugins gefunden, bei denen ich allerdings nicht wirklich folgen konnte wie das funktioniert (siehe http://drftpd.org/))
2. Hier mal ein Anfang den ich gemacht habe, aber ich bin mir relativ sicher, dass das eben kein guter ist ;-)
Wie funktioniert das besser? Bzw. ist das richtig, wie ich an die Sache rangeh? Und noch eine letzte Frage: die unloadPlugin()-Methode, wenn das Objekt aus der Liste entfernt wird, besteht es dann noch weiter oder wird es relativ schnell vom GC eingesammelt? Also, woher weiss der GC, nur weil ich ein Plugin aus der ArrayList<> rausschmeisse, dass es nun wirklich nichtmehr benutzt wird?
Ich hoffe ich hab euch nicht mal wieder zuviel Text gepresst ;-)
MfG
In letzter Zeit wollte ich bischen mehr über modulares Programmieren lernen, also hab ich mal gegoogled wie das denn so aussieht wenn man Plugins bei Laufzeit in sein Programm laden möchte.
Mein Szenario ist folgendes:
Ich habe ein Programm welches ueber TCP eine Verbindung zu einem Server herstellt (IRC Bot).
Nun kriegt das Programm laufend Nachrichten vom Server. Bei bestimmten Nachrichten/Triggern,
zB. wenn ein bestimmter Nutzer im Chat was schreibt, soll der Bot etwas bestimmtes machen.
Funktioniert alles einwandfrei.
Was ich mir nun überlegt habe:
Ok, jetzt will ich aber bei Laufzeit Plugins laden, die dann bei bestimmten Triggern etwas bestimmtes tun. Nehmen wir an ich schreibe ein Plugin my.domain.irc.bot.plugins.HeiseNews. Dieses Plugin (wird mit allen anderen geladenen Plugins) in einer ArrayList<PluginInterface> gespeichert, welches Instanzvariable der Klasse Bot ist.
Kommt jetzt wieder von einem Nutzer ein Befehl (der Nutzer schreibt dazu im Chat zB: !news), laufe ich die ArrayList<PluginInterface> durch und rufe in jedem Plugin eine Methode "messageEvent()" auf, die ggf. auch bestimmte Übergabeparameter beinhaltet (wie zB. sourceNick, derjenige der !news getriggert hat).
Jetzt zu meiner ersten Frage: Ist die Denkweise wie ich da ran geh in Ordnung oder kann ich mir viel Arbeit und Mühe mit einer anderen Methode, das umzusetzen, ersparen?
Zweite Frage(n):
1. Hat eventuell jemand ein schönes Beispiel bei dem Plugins in ein Test-Programm geladen werden? (Sollte leicht verständlich/nicht allzuviel Code sein, hab bisher nur Riesen-Projekte mit einem Interface für Plugins gefunden, bei denen ich allerdings nicht wirklich folgen konnte wie das funktioniert (siehe http://drftpd.org/))
2. Hier mal ein Anfang den ich gemacht habe, aber ich bin mir relativ sicher, dass das eben kein guter ist ;-)
Java:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Properties;
public class PluginManager {
private static ArrayList<PluginInterface> plugins = new ArrayList<PluginInterface>();
public static void loadPlugins() {
try {
Properties props = new Properties();
props.load(new FileInputStream("cfg/plugins.conf"));
for(int i = 1;; i++) {
String configuredPlugins = props.getProperty(i+".plugin");
if(configuredPlugins == null) break;
Class<?> clazz = Class.forName(configuredPlugins);
PluginInterface plugin = (PluginInterface) clazz.newInstance();
plugins.add(plugin);
System.out.println("Loaded "+plugin.getClass().getSimpleName());
}
} catch (FileNotFoundException e) {
System.out.println("Error, plugins.conf not found.");
} catch (IOException e) {
System.out.println("Error, plugins.conf could not be read.");
} catch (ClassNotFoundException e) {
System.out.println("Error loading a class.");
} catch (InstantiationException e) {
System.out.println("Instantiation exception while loading class.");
} catch (IllegalAccessException e) {
System.out.println("Could not access class.");
}
}
public static boolean unloadPlugin(PluginInterface plugin) {
return plugins.remove(plugin);
}
}
Wie funktioniert das besser? Bzw. ist das richtig, wie ich an die Sache rangeh? Und noch eine letzte Frage: die unloadPlugin()-Methode, wenn das Objekt aus der Liste entfernt wird, besteht es dann noch weiter oder wird es relativ schnell vom GC eingesammelt? Also, woher weiss der GC, nur weil ich ein Plugin aus der ArrayList<> rausschmeisse, dass es nun wirklich nichtmehr benutzt wird?
Ich hoffe ich hab euch nicht mal wieder zuviel Text gepresst ;-)
MfG
Zuletzt bearbeitet von einem Moderator: