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

时间:2014-05-05 11:19:17

标签: java dependency-injection javafx guice

我有一个JavaFX应用程序,我想介绍Guice,因为我的代码 现在充满了因子,只是为了测试。

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

在控制器类中,我有一个提供编辑/保存/删除操作的contactservice对象。 截至目前,我有一个该对象的接口,并提供一个实现和一个模拟。可以通过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和类似的框架,但我如何将这两者结合起来呢? 特别是如何让这些字段注入并自己实现控制器或者至少给它一些构造函数args?

4 个答案:

答案 0 :(得分:13)

我不使用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();

答案 1 :(得分:2)

对于称为afterburner.fx的javaFX,有一个很好的DI框架。看看它,我认为这是你正在寻找的工具。

答案 2 :(得分:0)

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

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

答案 3 :(得分:0)

要与 Guice 一起使用 JavaFx

  1. 在main方法上扩展javafx.application.Application并在该类上调用启动方法。这是应用程序的入口点。
  2. 实例化您选择的依赖项注入容器。例如。 Google Guice或Weld。
  3. 在应用程序的启动方法中,实例化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 Pscheidl ,他在 Integrating JavaFX 8 with Guice

处向我们提供了此智能代码