跳至主要内容

生命周期监听器 25.02

在 ChatGPT 中打开

AppLifecycleListener 接口使外部代码能够观察和响应应用生命周期事件。通过实现该接口,您可以在应用启动和关闭的特定时刻执行代码,而无需修改 App 类本身。

生命周期监听器会通过服务提供者配置文件在运行时自动发现和加载。每个应用实例都会接收自己的一组监听器实例,保持在同一环境中运行的不同应用之间的隔离。

何时使用生命周期监听器

当您需要时使用生命周期监听器:

  • 在应用运行之前初始化资源或服务
  • 当应用终止时清理资源
  • 添加跨切关注点而不修改 App
  • 构建插件架构

AppLifecycleListener 接口

AppLifecycleListener.java
public interface AppLifecycleListener {
default void onWillCreate(Environment env) {} // 自 25.03 起
default void onDidCreate(App app) {} // 自 25.03 起
default void onWillRun(App app) {}
default void onDidRun(App app) {}
default void onWillTerminate(App app) {}
default void onDidTerminate(App app) {}
}
应用隔离

每个应用实例都会接收自己的一组监听器实例:

  • 监听器在不同应用之间是隔离的
  • 监听器中的静态字段不会在不同应用之间共享
  • 监听器实例在应用启动时创建,并在应用终止时销毁

如果您需要在不同应用之间共享数据,请使用数据库或共享服务等外部存储机制。

生命周期事件

事件调用时机常见用途
onWillCreate 25.03在环境初始化后,应用创建之前修改配置,合并外部配置源
onDidCreate 25.03在应用实例化后,初始化之前早期应用级设置,注册服务
onWillRunapp.run() 执行之前初始化资源,配置服务
onDidRunapp.run() 成功完成后启动后台任务,记录成功启动信息
onWillTerminate在应用终止之前保存状态,为关闭做准备
onDidTerminate在应用终止之后清理资源,进行最终记录

创建生命周期监听器

基本实现

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) {
// 在应用创建之前修改配置
Config additionalConfig = ConfigFactory.parseString(
"myapp.feature.enabled = true"
);
env.setConfig(additionalConfig);
}

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

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

@Override
public void onDidRun(App app) {
System.out.println("应用已启动: " + app.getId());
}
}

注册监听器

创建一个服务提供者配置文件:

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

com.example.listeners.StartupListener
使用 AutoService

很容易忘记更新服务描述符。使用谷歌的 AutoService 自动生成服务文件:

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

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

控制执行顺序

当注册多个监听器时,您可以使用 @AppListenerPriority 注解来控制它们的执行顺序。当监听器相互之间有依赖关系或某些初始化必须在其他初始化之前进行时,这一点尤为重要。

优先级值按升序工作 - 较低的数字优先执行。默认优先级为10,因此没有显式优先级注释的监听器将在具有较低优先级值的监听器之后执行。

SecurityListener.java
@AutoService(AppLifecycleListener.class)
@AppListenerPriority(1) // 首先执行 - 关键安全设置
public class SecurityListener implements AppLifecycleListener {
@Override
public void onWillRun(App app) {
initializeSecurity();
}
}

@AutoService(AppLifecycleListener.class)
@AppListenerPriority(10) // 默认优先级 - 一般日志记录
public class LoggingListener implements AppLifecycleListener {
@Override
public void onWillRun(App app) {
initializeLogging();
}
}

与 App 钩子的执行流程

除控制多个监听器之间的顺序外,了解监听器与 App 类自身生命周期钩子之间的交互也很重要。对于每个生命周期事件,框架遵循特定的执行顺序,以确定您的监听器在相对于应用内置钩子的运行时机。

下图说明了此执行流程,显示了 AppLifecycleListener 方法相对于相应 App 钩子被调用的确切时机:

AppLifecycleListener 监听器与 App 钩子

错误处理

监听器抛出的异常会被记录,但不会阻止其他监听器执行或应用运行。始终在您的监听器中处理异常:

错误处理示例
@Override
public void onWillRun(App app) {
try {
riskyInitialization();
} catch (Exception e) {
logger.error("初始化失败", e);
}
}