Zum Hauptinhalt springen

Lebenszyklus-Listener 25.02

In ChatGPT öffnen

Das AppLifecycleListener-Interface ermöglicht externem Code, die App-Lebensereignisse zu beobachten und darauf zu reagieren. Durch die Implementierung dieses Interfaces können Sie Code zu spezifischen Zeitpunkten während des Starts und Herunterfahrens der App ausführen, ohne die App-Klasse selbst zu ändern.

Lebenszyklus-Listener werden zur Laufzeit automatisch über Dienstanbieter-Konfigurationsdateien entdeckt und geladen. Jede App-Instanz erhält ihre eigenen Satz von Listener-Instanzen, wodurch die Isolation zwischen verschiedenen Apps, die in derselben Umgebung ausgeführt werden, gewahrt bleibt.

Wann Lebenszyklus-Listener verwenden

Verwenden Sie Lebenszyklus-Listener, wenn Sie:

  • Ressourcen oder Dienste initialisieren müssen, bevor eine App läuft
  • Ressourcen bereinigen müssen, wenn eine App beendet wird
  • Querbeschneidungsanliegen hinzufügen möchten, ohne die App-Klasse zu ändern
  • Plugin-Architekturen aufbauen möchten

Das AppLifecycleListener-Interface

AppLifecycleListener.java
public interface AppLifecycleListener {
default void onWillCreate(Environment env) {} // Seit 25.03
default void onDidCreate(App app) {} // Seit 25.03
default void onWillRun(App app) {}
default void onDidRun(App app) {}
default void onWillTerminate(App app) {}
default void onDidTerminate(App app) {}
}
App-Isolation

Jede App-Instanz erhält ihre eigenen Satz von Listener-Instanzen:

  • Listener sind zwischen verschiedenen Apps isoliert
  • Statische Felder in Listenern werden nicht zwischen Apps geteilt
  • Listener-Instanzen werden erstellt, wenn die App startet, und werden zerstört, wenn sie beendet wird

Wenn Sie Daten zwischen Apps teilen müssen, verwenden Sie externe Speichermechanismen wie Datenbanken oder gemeinsame Dienste.

Lebenszyklusereignisse

EreignisWann aufgerufenHäufige Verwendungen
onWillCreate 25.03Nach der Initialisierung der Umgebung, vor der App-ErstellungKonfiguration ändern, externe Konfigurationsquellen zusammenführen
onDidCreate 25.03Nach der Instanziierung der App, vor der InitialisierungFrühe App-Einrichtungsmaßnahmen, Dienste registrieren
onWillRunBevor app.run() ausgeführt wirdRessourcen initialisieren, Dienste konfigurieren
onDidRunNachdem app.run() erfolgreich abgeschlossen istHintergrundaufgaben starten, erfolgreichen Start protokollieren
onWillTerminateVor der Beendigung der AppZustand speichern, auf Herunterfahren vorbereiten
onDidTerminateNach der Beendigung der AppRessourcen bereinigen, finales Protokollieren

Erstellen eines Lebenszyklus-Listeners

Grundimplementierung

StartupListener.java
import com.webforj.App;
import com.webforj.AppLifecycleListener;
import com.webforj.Environment;
import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory;

public class StartupListener implements AppLifecycleListener {

@Override
public void onWillCreate(Environment env) {
// Konfiguration vor der App-Erstellung ändern
Config additionalConfig = ConfigFactory.parseString(
"myapp.feature.enabled = true"
);
env.setConfig(additionalConfig);
}

@Override
public void onDidCreate(App app) {
System.out.println("App erstellt: " + app.getId());
}

@Override
public void onWillRun(App app) {
System.out.println("App startet: " + app.getId());
}

@Override
public void onDidRun(App app) {
System.out.println("App gestartet: " + app.getId());
}
}

Registrieren des Listeners

Erstellen Sie eine Dienstanbieter-Konfigurationsdatei:

Datei: src/main/resources/META-INF/services/com.webforj.AppLifecycleListener

com.example.listeners.StartupListener
Verwendung von AutoService

Es ist leicht zu vergessen, Dienstbeschreibungen zu aktualisieren. Verwenden Sie Googles AutoService, um die Dienstdatei automatisch zu generieren:

StartupListener.java
import com.google.auto.service.AutoService;

@AutoService(AppLifecycleListener.class)
public class StartupListener implements AppLifecycleListener {
// Implementierung
}

Steuerung der Ausführungsreihenfolge

Wenn mehrere Listener registriert sind, können Sie deren Ausführungsreihenfolge mithilfe der Annotation @AppListenerPriority steuern. Dies ist besonders wichtig, wenn Listener voneinander abhängig sind oder wenn bestimmte Initialisierungen vor anderen erfolgen müssen.

Prioritätswerte funktionieren in aufsteigender Reihenfolge - niedrigere Zahlen werden zuerst ausgeführt. Die Standardpriorität ist 10, sodass Listener ohne explizite Prioritätsannotation nach denen mit niedrigeren Prioritätswerten ausgeführt werden.

SecurityListener.java
@AutoService(AppLifecycleListener.class)
@AppListenerPriority(1) // Wird zuerst ausgeführt - kritische Sicherheitskonfiguration
public class SecurityListener implements AppLifecycleListener {
@Override
public void onWillRun(App app) {
initializeSecurity();
}
}

@AutoService(AppLifecycleListener.class)
@AppListenerPriority(10) // Standardpriorität - allgemeines Protokollieren
public class LoggingListener implements AppLifecycleListener {
@Override
public void onWillRun(App app) {
initializeLogging();
}
}

Ausführungsfluss mit App-Hooks

Neben der Steuerung der Reihenfolge zwischen mehreren Listenern ist es wichtig, zu verstehen, wie Listener mit den eigenen Lebenszyklus-Hooks der App-Klasse interagieren. Für jedes Lebenszyklusereignis folgt das Framework einer spezifischen Ausführungsreihenfolge, die bestimmt, wann Ihre Listener im Verhältnis zu den integrierten Hooks der App ausgeführt werden.

Das folgende Diagramm veranschaulicht diesen Ausführungsfluss und zeigt den genauen Zeitpunkt, wann die Methoden von AppLifecycleListener im Verhältnis zu den entsprechenden App-Hooks aufgerufen werden:

AppLifecycleListener listeners VS App hooks

Fehlerbehandlung

Ausnahmen, die von Listenern ausgelöst werden, werden protokolliert, verhindern jedoch nicht die Ausführung anderer Listener oder das Ausführen der App. Behandeln Sie immer Ausnahmen innerhalb Ihrer Listener:

Fehlerbehandlungsbeispiel
@Override
public void onWillRun(App app) {
try {
riskyInitialization();
} catch (Exception e) {
logger.error("Initialisierung fehlgeschlagen", e);
}
}