跳到主要内容

发射器

概述

Launcher本质上是对 main() 方法的高度抽象化和通用化实现。 它将模块和服务整合在一起,并管理应用程序的生命周期。

特点

  • ActiveJ Inject完美兼容
  • 可与 服务图表 ,以支持独立服务的启动/停止。
  • 提供了一种优雅地关闭服务的方法
  • 照顾到整个应用程序的生命周期和日志记录

简而言之,发射器

Launcher 是一个非常明确的工具。 你可以通过简单地看一下它的主方法 launch() 的实现来了解它是如何工作的,简而言之。

public void launch(String[] args) throws Exception {    logger.info("=== INJECTING DEPENDENCIES");    Injector injector = createInjector(args);    logger.info(" Eager instances:" injector.createEagerInstances());    Set<LauncherService> services = injector.getInstance(new Key<Set<LauncherService>>() {});    Set<LauncherService> startedServices = new HashSet<>();    logger.info(" Post-inject instances:" injector.postInjectInstances());
    logger.info("=== 启动应用");    logger.info("启动LauncherServices: " services);    startServices(services, startedServices);    onStart();    onStartFuture.complete(null);
    logger.info("===正在运行的应用程序");    run();    onRunFuture.complete(null);
    logger.info("===正在停止的应用程序");    onStop();    stopServices( startedServices);    onCompleteFuture.complete(null)。

逐步检查。

  • 创建 注射器模块Launcher中提供。
  • 将最高级别的依赖注入到 Launcher 实例本身。
  • 实例化所有标记为 @Eager Multibinder键组,由 Launcher的模块导出
  • Set<LauncherService> multibinder set中启动所有服务,由 Launcher's Modules输出,并执行 onStart() 方法
  • 执行 run() 方法
  • run() 完成后(由于完成了所有应用程序特定的计算,或响应了关闭请求,如SIGKILL),执行 onStop() 方法并停止所有服务。

下面是一个以日志形式表示的 Launcher 生命周期的例子(特别是。 HttpServerLauncher 子类,提供了一个 "AsyncHttpServer"。,一个 事件循环配置)。) 启动 这个 的例子。

public final class HttpHelloWorldExample extends HttpServerLauncher {  @Provides  AsyncServlet servlet() {    return request -> HttpResponse.ok200().withPlainText("Hello World");  }
  public static void main(String[] args) throws Exception {    Launcher launcher = new HttpHelloWorldExample();    launcher.launch(args);  }}

来看阿里巴巴的日志。

 === 注入DEPENDENCIES创建了急切的单子注入后的实例: [HttpHelloWorldExample]
=== 启动应用程序启动LauncherServices。[io.active.net.jmx.JmxModule, io.active.net.service.ServiceGraphModule]Starting LauncherService: io.active.net.jmx.JmxModuleStarting LauncherService: io.active.net.service.ServiceGraphModuleCreating ServiceGraph...启动服务[/0.0.0.0:8080] 上监听。AsyncHttpServer{listenAddresses=[/0.0.0.0:8080]}启动 io.active.net.http.AsyncHttpServer
=== RUNNING APPLICATIONHTTP Server is listening on http://localhost:8080/
=== STOPPING APPLICATIONStopping LauncherService: io.active.net.dmx.JmxModule.active.net.jmx.JmxModuleStopping LauncherService: io.active.net.service.ServiceGraphModuleStopping ServiceGraph...停止服务
  • 启动器 ,可选择要求其 模块的以下依赖性。
    • @Eager multibinder keygroup
    • 套装<LauncherService> 多装订套装

启动器 将以下依赖关系导出到其 模块

class Launcher{    @NotNull    public final Injector createInjector() {       return Injector.of(getInternalModule()                      .combinedWith(getModule()                      .overrideWith(getOverrideModule() ));    }
  private Module getInternalModule() {     Class<Launcher> launcherClass = (Class<Launcher>) getClass();     Key<CompletionStage<Void>> completionStageKey = new Key<CompletionStage<Void>>() {};
     return Module.create()         .bind(String[] .class) .annotatedWith(Args.class) .toInstance(args)         .bind(Launcher.class).to(launcherClass)         .bind(launcherClass).toInstance(this)
         .postInjectInto(launcherClass)         .bind(completionalStageKey.named(OnStart.class)) .toInstance(onStartFuture)         .bind(completionStageKey.named(OnRun.class)).toInstance(onRunFuture)         .bind(completionStageKey.named(OnComplete.class)) .toInstance(onCompleteFuture)
         .scan(Launcher.this);    }
  //这个方法可以被扩展Launcher的子类所重写,  //提供业务逻辑模块(例如,ConfigModule)  protected Module getModule() {      return Module.empty();  }
  // 这个方法可以被扩展Launcher的子类所覆盖,  // 覆盖内部模块的定义  protected Module getOverrideModule() {      return Module.empty();  }}
  • @Args String[]Launcher.launch(String[] args) 方法的参数,对应于 main(String[] args) 方法
  • Launcher 实例本身
  • @OnStart CompletionStage<Void> 未来,当应用程序被连接并启动时,就会完成。
  • @OnRun CompletionStage<Void> 未来,当 Launcher.run() 完成时,就完成了。
  • @OnComplete CompletionStage<Void> 未来,当应用程序停止时就会完成。

Launcher 也有方便的诊断和JMX属性。

  • 启动、开始、运行、停止和完成的瞬间
  • 开始、运行、停止和总时间的持续时间
  • Throwable applicationError property

更多例子

note

要运行例子,你需要从GitHub克隆ActiveJ

git clone https://github.com/activej/activej

并将其作为一个Maven项目导入。 查看标签 v5.4.3。 在运行这些例子之前,先建立项目。 这些例子位于 activej/examples/core/datastream。

Hello World实例

这里是一个使用ActiveJ Inject的简单的 "Hello World "启动器应用程序。

public final class HelloWorldExample extends Launcher {  @Inject  String message;
  @Provides  String message() {    return "Hello, world!";  }
  @Override  protected void run() {    System.out.println(message);  }
  public static void main(String[] args) throws Exception {    Launcher launcher = new HelloWorldExample();    launcher.launch(args);  }}

在GitHub上看到完整的例子

使用Launcher从头开始创建HTTP服务器

当创建HTTP服务器或任何其他应用程序时,你可以使用一些预定义的解决方案 (见例子) 或简单的Launcher代替。 在这种 的情况下,你需要处理所有需要的依赖关系,并覆盖一些基本方法。

public final class CustomHttpServerExample extends Launcher {  private static final int PORT = 8080;
  @Provides  Eventloop eventloop() {    return Eventloop.create();  }
  @Provides  AsyncServlet servlet() {    return request -> HttpResponse.ok200()        .withPlainText("Hello from HTTP server");  }
  @Provides  @Eager  AsyncHttpServer server(Eventloop eventloop, AsyncServlet servlet) {    return AsyncHttpServer.create(eventloop, servlet).withListenPort(PORT);  }
  @Override  protected Module getModule() {    return ServiceGraphModule.create();  }
  @Override  protected void run() throws Exception {    logger.info("HTTP Server is now available at http://localhost:" + PORT);    awaitShutdown();  }
  public static void main(String[] args) throws Exception {    Launcher launcher = new CustomHttpServerExample();    launcher.launch(args);  }}

在GitHub上看到完整的例子

使用程序参数的工作

要从 Launcher 内访问程序参数,你需要将这些参数传递给 Launcher#launch 方法。 然后有两种访问参数的方式: - 使用 启动器's String[] args 领域 - 使用依赖注入请求参数。 一个键是 String[].class ,用 @Args 注解来说明。 下面的例子说明了这两种情况。

public final class LauncherArgsExample extends Launcher {
  @Inject  Injector injector;
  @Override  protected void run() {    System.out.println("Received args: " + Arrays.toString(args));
    String[] injectedArgs = injector.getInstance(Key.of(String[].class, Args.class));    System.out.println("Args retrieved from DI: " + Arrays.toString(injectedArgs));  }
  public static void main(String[] args) throws Exception {    new LauncherArgsExample().launch(args);  }}

在GitHub上看到完整的例子