在 JavaFX 中添加 Spring 依赖注入(JPA Repo、Service) [英] Adding Spring Dependency Injection in JavaFX (JPA Repo, Service)

查看:196
本文介绍了在 JavaFX 中添加 Spring 依赖注入(JPA Repo、Service)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 java FX 基本应用程序,它有一个简单的场景(一个表单).我有一个 Mysql Db,我正在使用 Spring JPA(spring data jpa,即存储库/实体)与之交互.

I have a java FX basic application which has a simple Scene(a form). I have a Mysql Db and I am using Spring JPA (spring data jpa i.e repository/entities) to interact with the same.

现在,因为我们知道 javaFx 有一些生命周期钩子,即:在里面()开始()和停止().

Now, since we know that javaFx has some lifecycle hooks namely: init() start() and stop().

假设我想使用 JPA save() 方法在数据库中插入数据.通常,如果是我的控制器,则是正常的数据库注入,例如:

Let's say I want to insert data in Database using JPA save() method. Usually, if it was my controller, a normal DB injection like:

@Autowired
EmployeeRepo employeeRepo;

本来可以的.但是,我无法在生命周期方法中访问此(或任何自动装配注入).

Would have worked. But, I am not able to access this (or any Autowired Injection) inside the lifecycle methods.

public void start(Stage primaryStage) throws Exception {

// Some Code

employeeRepo.findAll() <- This is returning null

但是,当我添加一个测试方法并使用相同的方法时,它工作正常:

However, when I add a test method and use the same, It works fine:

@PostConstruct
public void test() {
// Repo object is not giving null
}

有没有一种方法可以手动将依赖项注入我的按钮侦听器中或将其传递给启动方法.

Is there a way I can manually inject the dependencies inside my button listener or pass it to the launch method.

请告诉我是否有解决方案,因为我是 JavaFX 的新手

Please let me know if there is a solution as I am new to JavaFX

推荐答案

JavaFX 的依赖注入选项

有多种方法可以将依赖注入到 JavaFX 应用程序中.例如 Gluon 有一个名为 Gluon Ignite 的项目,它为各种依赖注入框架启用 JavaFX 应用程序,例如Guice、Spring 和 Dagger.

There are numerous ways to get dependency injection into a JavaFX application. For example Gluon have a project called Gluon Ignite which enables JavaFX application for various dependency injection frameworks, such as Guice, Spring and Dagger.

由于您已选择 Spring 作为您的依赖注入框架,并且您希望使用一堆其他 Spring 设施,例如 Spring Data 存储库,您可能希望考虑使用 SpringBoot 应用程序.

As you have chosen Spring for your dependency injection framework and you wish to use a bunch of other Spring facilities such as Spring Data repositories, you may wish to consider using a SpringBoot application.

您可以使您的 JavaFX 应用程序成为 SpringBoot 应用程序(尽管这并不是为了获得依赖注入而严格必要的),以便在您的应用程序中获得一堆可用的 Spring 工具.如果您四处搜索,网上有一些相关教程.

You could make your JavaFX application a SpringBoot application (though this isn't strictly necessary just to get dependency injection) in order to get a bunch of Spring facilities available within your application. There are some tutorials on that on the web if you search around.

Spring 和 JavaFX 的基本示例集成

以下是将 JavaFX 与 SpringBoot 应用程序集成的教程示例:

Here is an example of a tutorial on integrating JavaFX with a SpringBoot application:

该示例的一个关键部分是应用程序的 init() 方法(我刚刚在此处复制、粘贴和复制以供参考):

A critical part of that example is the init() method of the application (which I have just copy and pasted and reproduced here for reference):

@SpringBootApplication
public class DemoApplication extends Application {

    private ConfigurableApplicationContext springContext;
    private Parent root;

    @Override
    public void init() throws Exception {
        springContext = SpringApplication.run(DemoApplication.class);
        FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/sample.fxml"));
        fxmlLoader.setControllerFactory(springContext::getBean);
        root = fxmlLoader.load();
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        primaryStage.setTitle("Hello World");
        Scene scene = new Scene(root, 800, 600);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    @Override
    public void stop() throws Exception {
        springContext.stop();
    }


    public static void main(String[] args) {
        launch(DemoApplication.class, args);
    }
}

示例应用程序正在运行 SpringBoot 应用程序以启动 Spring 系统并让它在 init 方法中提供应用程序上下文.然后应用程序使用 FXMLLoader setControllerFactory() 方法允许 Spring 实例化 FXML 控制器并在应用程序中注入对 Spring bean 的引用.

The sample app is running the SpringBoot application to startup the Spring system and have it provide an application context in the init method. The app then uses the FXMLLoader setControllerFactory() method to allow Spring to instantiate FXML controllers and inject references to Spring beans in the application.

自动连接您的 JavaFX 控制器

为了让您的 JAVAFX FXML 控制器自动装配,除了以下调用 FXMLLoader 之外:

To get your JAVAFX FXML controller autowired, in addition to the following call one the FXMLLoader:

fxmlLoader.setControllerFactory(springContext::getBean);

您还需要在您希望控制器使用的任何 Spring 依赖项中将您的类注释为 Spring @Component@Autowired.通过这种方式,FXMLLoader 将基于 @FXML 的引用注入到您的 UI 元素,并且还将委托给 spring 上下文来注入 Spring 依赖项.

You also need to annotate your class as a Spring @Component, and @Autowired in any Spring dependencies you want your controller to use. In this way, the FXMLLoader will inject the @FXML based references to your UI elements and it will also delegate to the spring context to inject the Spring dependencies.

@Component
public class DemoController {
    @FXML
    private Label usernameLabel; 

    @Autowired
    public void mySpringService;

    public void initialize() {
        usernameLabel.setText(
            mySpringService.getLoggedInUsername()
        );
    }
}

注意,Spring 有一个 @Controller 注释,它可用于注释 JavaFX 控制器而不是 @Component 注释,但我建议避免使用 @Controller 用于此目的,而是用于 Spring REST 服务端点控制器定义的 @Controller 注释.

Note, Spring has an @Controller annotation, which could be used to annotate the JavaFX controller rather than the @Component annotation, but I would recommend avoiding use of @Controller for that purpose, and instead @Controller annotation for Spring REST service endpoint controller definitions.

Spring Boot 应用程序和 JavaFX 应用程序之间的关注点分离

您可能需要注意的一件事是运行 SpringBoot 应用程序,生成应用程序的新实例,并且您已经有一个由 JavaFX 系统启动的 JavaFX 应用程序实例,因此如果出现以下情况,将导致两个 JavaFX 应用程序实例SpringBoot 应用程序和 JavaFX 应用程序基于相同的类(如上所示),这可能会造成混淆.

One thing you might want to be careful of is that running the SpringBoot application, generates a new instance of the application and you already have a JavaFX application instance launched by the JavaFX system, so that would result in two JavaFX application instances if the SpringBoot application and the JavaFX application are based upon the same class (as shown above), which would potentially be confusing.

因此,最好将 Spring 应用程序和 JavaFX 应用程序分开.这增强了应用程序的 UI 和服务部分之间关注点的分离,并使测试更容易,因为 Spring 应用程序可以独立于启动和关闭 JavaFX 应用程序进行单元测试.

So it may is likely better to separate out the Spring application and the JavaFX application. This enhances the separation of concerns between the UI and service portions of the application and makes for easier testing as the Spring application can be unit tested independently of of starting up and shutting down the JavaFX application.

自动连接 JavaFX 应用程序类

注意,使用上述设置,它不会自动装配 JavaFX 应用程序类实例化的实例.如果您希望这样做,您可以使用下面说明的技术在 JavaFX 实例化应用程序类中注入 bean:

Note, using the above setup, it will not autowire the JavaFX application class instantiated instance. If you wish to do that, you can use the technique illustrated below to inject beans in the JavaFX instantiated application class:

将以下代码放入应用程序的 init 方法中:

Place the following code inside your application's init method:

springContext
    .getAutowireCapableBeanFactory()
    .autowireBeanProperties(
        this,
        AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, 
        true
    );

mvvmFX 框架使用与上述类似的方法将 SpringBoot 与 JavaFX 应用程序集成:

The mvvmFX framework uses a similar method to that outlined above to integrate SpringBoot with JavaFX applications:

将命令行参数从 JavaFX 传递到 SpringBoot

要将参数从 JavaFX 应用程序传递到 SpringBoot 应用程序,请使用:

To pass arguments from the JavaFX application to the SpringBoot application, use:

SpringApplication.run(
    DemoApplication.class, 
    getParameters().getRaw().toArray(new String[0])
);

其他问题

如果您需要更多地控制 SpringApplication 的启动,您可以使用 SpringApplicationBuilder 例如:

If you need, even more control over the startup of the SpringApplication, you can use the SpringApplicationBuilder for example:

ConfigurableApplicationContext startupContext =
        new SpringApplicationBuilder(DemoApplication.class)
                .web(WebApplicationType.NONE)
                .run(args);

这个答案只是为您提供有关如何解决这个问题的提示,而不是作为关于如何将依赖注入与 JavaFX 集成的通用指南,这可能最终成为一个非常棘手的主题,需要全面覆盖.

This answer is just written to give you hints on how you might approach this problem rather than as a general purpose guide on how to integrate dependency injection with JavaFX, which could end being quite a tricky subject to cover comprehensively.

这篇关于在 JavaFX 中添加 Spring 依赖注入(JPA Repo、Service)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆