在JavaFX中添加Spring依赖注入(JPA存储库,服务) [英] Adding Spring Dependency Injection in JavaFX (JPA Repo, Service)

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

问题描述

我有一个具有简单场景(表单)的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具有一些生命周期挂钩,即: 在里面() start()和stop().

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应用程序可用于各种依赖项注入框架,例如吉斯,春天和匕首.

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,而应避免使用@Controller注释Spring REST服务端点控制器定义.

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和服务部分之间关注点的分离,并使得测试变得更加容易,因为可以独立于启动和关闭JavaFX应用程序而对Spring应用程序进行单元测试.

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存储库,服务)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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