繁体   English   中英

如何在 JavaFX 控制器中使用 Guice?

[英]How can i use Guice in JavaFX controllers?

我有一个 JavaFX 应用程序,我想在其中引入 Guice,因为我的代码现在充满了工厂,仅用于测试目的。

我有一个用例,我有一个特定视图的控制器类。 这个控制器类有一个视图模型,我通过控制器类的构造函数将模型传递给视图模型。

在控制器类中,我有一个 contactservice 对象,它提供编辑/保存/删除操作。 到目前为止,我有一个该对象的接口,并提供了一个实现和一个 Mock。 可以通过 Factory.getInstance() 方法检索此对象。

我想做的是这样的:

public class NewContactController implements Initializable {
    // ------------------------------------------------------------------------
    // to inject by guice
    // ------------------------------------------------------------------------
    private ContactService contactService;

    @Inject
    public void setContactService(ContactService srv) {
        this.contactService = srv;
    }
    // edit window
    public NewContactController(Contact c) {
        this.viewModel = new NewContactViewModel(c);
    }
    // new window
    public NewContactController() {
        this.viewModel = new NewContactViewModel();
    }

    @FXML
    void onSave(ActionEvent event) {
        //do work like edit a contcat, 
        contactService.editContact(viewModel.getModelToSave());
    }

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        // bind to viewmodel---------------------------------------------------
    }
}

我怎样才能做到这一点? 做这样的事情是个好主意吗? 当我在寻找解决方案时,我发现了fx-guice和类似的框架,但我如何将这两者结合起来? 特别是我怎样才能让这个字段被注入并自己实例化控制器,或者至少给它一些构造函数参数?

我不使用 Guice,但最简单的方法似乎只是在FXMLLoader上使用控制器工厂。 您可以创建一个控制器工厂,指示FXMLLoader使用 Guice 来初始化您的控制器:

final Injector injector = Guice.createInjector(...);
FXMLLoader loader = new FXMLLoader(getClass().getResource(...));
loader.setControllerFactory(new Callback<Class<?>, Object>() {
   @Override
   public Object call(Class<?> type) {
       return injector.getInstance(type);
   }
});
// In Java 8, replace the above with 
// loader.setControllerFactory(injector::getInstance);
Parent root = loader.<Parent>load();

javaFX 有一个很好的 DI 框架,称为afterburner.fx 检查一下,我认为这是您正在寻找的工具。

假设您(可以)手动/guice 而不是从 FXML 实例化控制器,如果您需要将任何非 DIable 参数传递给构造函数,则可以使用https://github.com/google/guice/wiki/AssistedInject 然后,您可以使用 .setController(this) 将控制器手动设置为 FXMLLoader,并在控制器的构造函数中加载 FXML 文件。

不确定是否有任何缺点,但这种系统似乎对我有用:)

JavaFxGuice结合使用:

  1. 扩展 javafx.application.Application 并从 main 方法调用该类的启动方法。 这是应用程序的入口点。
  2. 实例化您选择的依赖注入容器。 例如 Google Guice 或 Weld。
  3. 在应用程序的 start 方法中,实例化 FXMLLoader 并设置它的控制器工厂以从容器中获取控制器。 理想情况下,使用提供程序从容器本身获取 FXMLLoader。 然后给它一个 .fxml 文件资源。 这将创建新创建窗口的内容。
  4. 将上一步中实例化的 Parent 对象提供给 Stage 对象(通常称为 primaryStage)作为 start(Stage primaryStage) 方法的参数。
  5. 通过调用它的 show() 方法来显示 primaryStage。

代码示例MyApp.java

public class MyApp extends Application {
    @Override
    public void start(Stage primaryStage) throws IOException {
        Injector injector = Guice.createInjector(new GuiceModule());
        //The FXMLLoader is instantiated the way Google Guice offers - the FXMLLoader instance
        // is built in a separated Provider<FXMLLoader> called FXMLLoaderProvider.
        FXMLLoader fxmlLoader = injector.getInstance(FXMLLoader.class);

        try (InputStream fxmlInputStream = ClassLoader.getSystemResourceAsStream("fxml\\login.fxml")) {
            Parent parent = fxmlLoader.load(fxmlInputStream);
            primaryStage.setScene(new Scene(parent));
            primaryStage.setTitle("Access mini Stock App v1.1");
            primaryStage.show();
            primaryStage.setOnCloseRequest(e -> {
                System.exit(0);
            });
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    public static void main(String[] args) {

        launch();
    }

}

然后 FXMLLoaderProvider.java

public class FXMLLoaderProvider implements Provider<FXMLLoader> {
    
        @Inject Injector injector;
    
        @Override
        public FXMLLoader get() {
            FXMLLoader loader = new FXMLLoader();
            loader.setControllerFactory(p -> {
                return injector.getInstance(p);
            });
            return loader;
        }
    
    }

感谢先生。 Pavel PscheidlIntegrating JavaFX 8 with Guice 上为我们提供了这个智能代码

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM