Écouteurs de cycle de vie 25.02
L'interface AppLifecycleListener permet au code externe d'observer et de répondre aux événements du cycle de vie de l'application. En implémentant cette interface, vous pouvez exécuter du code à des moments spécifiques pendant le démarrage et l'arrêt de l'application sans modifier la classe App elle-même.
Les écouteurs de cycle de vie sont automatiquement découverts et chargés à l'exécution via des fichiers de configuration de fournisseur de services. Chaque instance d'application reçoit son propre ensemble d'instances d'écouteurs, maintenant ainsi l'isolement entre différentes applications fonctionnant dans le même environnement.
Quand utiliser les écouteurs de cycle de vie
Utilisez les écouteurs de cycle de vie quand vous devez :
- Initialiser des ressources ou des services avant qu'une application ne s'exécute
- Nettoyer des ressources lorsque l'application se termine
- Ajouter des préoccupations transversales sans modifier la classe
App - Construire des architectures de plugins
L'interface AppLifecycleListener
public interface AppLifecycleListener {
default void onWillCreate(Environment env) {} // Depuis 25.03
default void onDidCreate(App app) {} // Depuis 25.03
default void onWillRun(App app) {}
default void onDidRun(App app) {}
default void onWillTerminate(App app) {}
default void onDidTerminate(App app) {}
}
Chaque instance d'application reçoit son propre ensemble d'instances d'écouteurs :
- Les écouteurs sont isolés entre différentes applications
- Les champs statiques dans les écouteurs ne seront pas partagés entre les applications
- Les instances d'écouteurs sont créées lorsque l'application démarre et détruites lorsqu'elle se termine
Si vous devez partager des données entre des applications, utilisez des mécanismes de stockage externes comme des bases de données ou des services partagés.
Événements de cycle de vie
| Événement | Quand est-il appelé | Usages courants |
|---|---|---|
onWillCreate 25.03 | Après l'initialisation de l'environnement, avant la création de l'application | Modifier la configuration, fusionner des sources de configuration externes |
onDidCreate 25.03 | Après l'instanciation de l'application, avant l'initialisation | Configuration précoce au niveau de l'application, enregistrer des services |
onWillRun | Avant l'exécution de app.run() | Initialiser des ressources, configurer des services |
onDidRun | Après que app.run() soit terminé avec succès | Démarrer des tâches en arrière-plan, enregistrer un démarrage réussi |
onWillTerminate | Avant la terminaison de l'application | Sauvegarder l'état, se préparer à l'arrêt |
onDidTerminate | Après la terminaison de l'application | Nettoyer les ressources, journaliser final |
Création d'un écouteur de cycle de vie
Implémentation de base
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) {
// Modifier la configuration avant la création de l'application
Config additionalConfig = ConfigFactory.parseString(
"myapp.feature.enabled = true"
);
env.setConfig(additionalConfig);
}
@Override
public void onDidCreate(App app) {
System.out.println("Application créée : " + app.getId());
}
@Override
public void onWillRun(App app) {
System.out.println("Application en démarrage : " + app.getId());
}
@Override
public void onDidRun(App app) {
System.out.println("Application démarrée : " + app.getId());
}
}
Enregistrement de l'écouteur
Créez un fichier de configuration de fournisseur de services :
Fichier : src/main/resources/META-INF/services/com.webforj.AppLifecycleListener
com.example.listeners.StartupListener
Il est facile d'oublier de mettre à jour les descripteurs de service. Utilisez le AutoService de Google pour générer automatiquement le fichier de service :
import com.google.auto.service.AutoService;
@AutoService(AppLifecycleListener.class)
public class StartupListener implements AppLifecycleListener {
// Implémentation
}
Contrôle de l'ordre d'exécution
Lorsque plusieurs écouteurs sont enregistrés, vous pouvez contrôler leur ordre d'exécution à l'aide de l'annotation @AppListenerPriority. Cela est particulièrement important lorsque les écouteurs ont des dépendances les uns envers les autres ou lorsque certaines initialisations doivent se produire avant d'autres.
Les valeurs de priorité fonctionnent par ordre croissant - les nombres plus bas s'exécutent en premier. La priorité par défaut est 10, donc les écouteurs sans annotations de priorité explicites s'exécuteront après ceux avec des valeurs de priorité plus basses.
@AutoService(AppLifecycleListener.class)
@AppListenerPriority(1) // S'exécute en premier - configuration de sécurité critique
public class SecurityListener implements AppLifecycleListener {
@Override
public void onWillRun(App app) {
initializeSecurity();
}
}
@AutoService(AppLifecycleListener.class)
@AppListenerPriority(10) // Priorité par défaut - journalisation générale
public class LoggingListener implements AppLifecycleListener {
@Override
public void onWillRun(App app) {
initializeLogging();
}
}
Flux d'exécution avec des crochets App
Au-delà du contrôle de l'ordre entre plusieurs écouteurs, il est important de comprendre comment les écouteurs interagissent avec les propres crochets de cycle de vie de la classe App. Pour chaque événement de cycle de vie, le framework suit une séquence d'exécution spécifique qui détermine quand vos écouteurs s'exécutent par rapport aux crochets intégrés de l'application.
Le diagramme ci-dessous illustre ce flux d'exécution, montrant le moment précis où les méthodes AppLifecycleListener sont appelées par rapport aux crochets correspondants de l'App :
Gestion des erreurs
Les exceptions levées par les écouteurs sont enregistrées mais ne empêchent pas les autres écouteurs de s'exécuter ou l'application de fonctionner. Gérez toujours les exceptions au sein de vos écouteurs :
@Override
public void onWillRun(App app) {
try {
riskyInitialization();
} catch (Exception e) {
logger.error("L'initialisation a échoué", e);
}
}