将依赖项注入 Java fx 应用程序

问题描述 投票:0回答:2

可能我错过了一些东西,但我正在努力寻找一个解决方案,如何将依赖项(例如事件总线的实例和一些服务接口)传递到我的 javafx 应用程序。

我有一个 UI-Init 类,它只不过是启动应用程序并接收 UI 的一些依赖项(如 eventBus):

public class Frontend {

public Frontend(MBassador<EventBase> eventBus) {
    Application.launch(AppGui.class);
}

我的 AppGui 类扩展了 Application 并加载 FXML:

public class AppGui extends Application {

private Stage primaryStage;
private GridPane rootLayout;

@Override
public void start(Stage primaryStage) {
    this.primaryStage = primaryStage;
    try {
        // Load root layout from fxml file.
        FXMLLoader loader = new FXMLLoader();
        loader.setLocation(getClass().getResource("RootLayout.fxml"));
        rootLayout = (GridPane) loader.load();

        // Show the scene containing the root layout.
        Scene scene = new Scene(rootLayout);
        scene.setFill(null);
        primaryStage.setScene(scene);

        RootLayoutController rootController = loader.getController();
        rootController.init(/*here I would like to inject my eventBus*/);

        primaryStage.show();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

现在,我如何将我的 eventBus 和其他服务接口传递给这个控制器?我读过有关使用 guice(JavaFX 控制器如何访问其他服务?)或 afterburner.fx 等 DI 框架的信息来使用它。但即使我在应用程序的其余部分使用 guice,我还是需要将 Injector 实例传递给 JavaFX 应用程序?.

但是Application.launch(AppGui.class);是静态的,并在 javafx 线程上内部创建一个 AppGui 实例,我无法访问该实例。那么如何在不使用静态变量的情况下将依赖项注入到我的 AppGui 对象中呢?

javafx javafx-8
2个回答
4
投票

这就是我所做的:

Application
类有几个生命周期回调,
init()
stop()

来自 Javadoc

public void init() throws java.lang.Exception

应用程序初始化方法。在加载并构造 Application 类后立即调用此方法。应用程序可以重写此方法以在应用程序实际启动之前执行初始化。

public void stop() throws java.lang.Exception

当应用程序应该停止时调用此方法,并提供一个方便的地方来准备应用程序退出和销毁资源。

同样来自 Javadocs,生命周期:

  1. 构造指定
    Application
    类的实例
  2. 调用
    init()
    方法
  3. 调用
    start(javafx.stage.Stage)
    方法
  4. 等待应用程序完成,当发生以下任一情况时会发生这种情况:
    • 应用程序调用
      Platform.exit()
    • 最后一个窗口已关闭,
      implicitExit
      上的
      Platform
      属性为
      true
  5. 调用 stop() 方法

我在 init() 中启动

控制反转 (IoC)
容器,并在
stop()
中停止它。现在我的
Application
类有了对 IoC 容器的引用,并且可以为第一个控制器提供其依赖项。

事实上,我让IoC框架来管理控制器。我使用

FXMLLoader.setController()
将它们设置为加载的 FXML,而不是使用
fx:controller
指定它们。


0
投票

您可以在调用

launch()
之前传递对应用程序类的静态引用。比如:

public class Frontend {
    public Frontend(MBassador<EventBase> eventBus) {
        AppGui.setEventBus(eventBus);
        Application.launch(AppGui.class);
    }
}

public class AppGui extends Application {
    private static MBassador<EventBase> eventBus;
    public static void setEventBus(MBassador<EventBase> eventBus) {
        this.eventBus = eventBus;
    }

    private MBassador<EventBase> eventBus;

    @Override
    public void init() {
        if (AppGui.eventBus == null) {
            throw new IllegalStateException(); 
            // or however you want to handle that state
        } else {
            this.eventBus = AppGui.eventBus;
            AppGui.eventBus = null; 
        }
    }
}

是否保留并使用静态引用,或者将静态引用复制到本地引用取决于您和应用程序的设计。如果您希望实例化多个 AppGui 副本,则可能需要本地引用。

不知道这是否是线程安全的(可能不是)。 @Nikos 和 @James_D 的建议是可靠且首选的......但有时您只需要一个技巧。 :) YMMV

© www.soinside.com 2019 - 2024. All rights reserved.