依赖注入和JavaFX

依赖注入和JavaFX,java,javafx,dependency-injection,Java,Javafx,Dependency Injection,由于JavaFX运行时希望实例化我的应用程序对象和所有控制器对象,因此如何将依赖项注入这些对象 如果对象由DI框架(如Spring)实例化,该框架将连接所有依赖项。如果我手动实例化对象,我将通过构造函数参数提供依赖项。但是在JavaFX应用程序中我该怎么做呢 谢谢 您可以为FXMLLoader指定一个。控制器工厂是一个将控制器类映射到将用作控制器的对象(可能是,但不一定是该类的实例)的函数 因此,如果您希望Spring为您创建控制器实例,这可以非常简单: ApplicationContext c

由于JavaFX运行时希望实例化我的应用程序对象和所有控制器对象,因此如何将依赖项注入这些对象

如果对象由DI框架(如Spring)实例化,该框架将连接所有依赖项。如果我手动实例化对象,我将通过构造函数参数提供依赖项。但是在JavaFX应用程序中我该怎么做呢

谢谢

您可以为
FXMLLoader
指定一个。控制器工厂是一个将控制器类映射到将用作控制器的对象(可能是,但不一定是该类的实例)的函数

因此,如果您希望Spring为您创建控制器实例,这可以非常简单:

ApplicationContext context = ... ;

FXMLLoader loader = new FXMLLoader(getClass().getResource("path/to/fxml"));
loader.setControllerFactory(context::getBean);
Parent root = loader.load();
SomeController controller = loader.getController(); // if you need it...
// ...
现在,
fxmloader
将通过调用
context.getBean(c)为
类c
创建控制器实例

例如,您可以有一个配置:

@Configuration
public class AppConfig {

    @Bean
    public MyService service() {
        return new MyServiceImpl();
    }

    @Bean
    @Scope("prototype")
    public SomeController someController() {
        return new SomeController();
    }

    // ...
}

如果您不使用DI框架,并且您想“手工”进行注入,那么您可以这样做,但这涉及到使用大量反射。以下内容展示了Spring是如何(并将让您了解Spring为您做了多少丑陋的工作!):


最后,您可能想检查一下,这是一个非常轻量级(以所有最佳方式)的JavaFX特定DI框架。(它使用了一种约定优于配置的方法,您只需将FXML文件名与控制器类名匹配,还可以选择CSS文件名,一切正常。)

我使用FXMLLoader类的setControllerFactory方法来设置此序列化程序使用的控制器工厂

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception{
        AnnotationConfigApplicationContext ctx=new AnnotationConfigApplicationContext();
        ctx.register(AppConfig.class);
        ctx.refresh();
        FXMLLoader loader = new FXMLLoader(getClass().getResource("../view/sample.fxml"));
        loader.setControllerFactory(ctx::getBean);

        Parent root = loader.load();
        Controller controller = loader.getController();
        primaryStage.setTitle("Hello World");
        primaryStage.setScene(new Scene(root, 925, 400));
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);

    }
}
然后使用@component创建控制器类

  @Component
        public class Controller {
            @Autowired
            private ItemController itemController;
            @FXML
            private TextField item;
            @FXML
            private TextField quantity;
        }
public class SomeController {

    private final MyService service ;

    public SomeController(MyService service) {
        this.service = service ;
    }

    // injected by FXMLLoader:
    @FXML
    private TextField someTextField ;

    public void initialize() {
        someTextField.setText(service.getSomeText());
    }

    // event handler:
    @FXML
    private void performAction(ActionEvent e) {
        service.doAction(...);
    }
}
public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception{
        AnnotationConfigApplicationContext ctx=new AnnotationConfigApplicationContext();
        ctx.register(AppConfig.class);
        ctx.refresh();
        FXMLLoader loader = new FXMLLoader(getClass().getResource("../view/sample.fxml"));
        loader.setControllerFactory(ctx::getBean);

        Parent root = loader.load();
        Controller controller = loader.getController();
        primaryStage.setTitle("Hello World");
        primaryStage.setScene(new Scene(root, 925, 400));
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);

    }
}
  @Component
        public class Controller {
            @Autowired
            private ItemController itemController;
            @FXML
            private TextField item;
            @FXML
            private TextField quantity;
        }