当前位置: 首页 > 面试题库 >

在JavaFX中添加Spring依赖注入(JPA存储库,服务)

农波涛
2023-03-14
问题内容

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

现在,由于我们知道javaFx有一些生命周期挂钩,即:init()start()和stop()。

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

@Autowired
EmployeeRepo employeeRepo;

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

public void start(Stage primaryStage) throws Exception {

// Some Code

employeeRepo.findAll() <- This is returning null

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

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

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

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


问题答案:

JavaFX的依赖项注入选项

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

在为依赖项注入框架选择了Spring并希望使用大量其他Spring工具(例如Spring
Data存储库)之后,您可能希望考虑使用SpringBoot应用程序。

您可以将JavaFX应用程序设为SpringBoot应用程序(尽管严格来说,这并不是为了获得依赖注入而必须这样做),以便在应用程序中获得大量Spring设施。如果您四处搜寻,网上会有一些教程。

Spring和JavaFX的基本示例集成

这是有关将JavaFX与SpringBoot应用程序集成的教程的示例:

  • 让Spring成为您的JavaFX Controller Factory

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

@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的引用。

自动接线JavaFX控制器

要自动连接您的JAVAFX FXML控制器,除了以下调用,还需要调用FXMLLoader:

fxmlLoader.setControllerFactory(springContext::getBean);

您还需要将类注释为Spring@Component,并且@Autowired在您希望控制器使用的任何Spring依赖项中。这样,FXMLLoader将注入基于@FXML的对UI元素的引用,还将委托给Spring上下文以注入Spring依赖项。

@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服务端点控制器定义注释。

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

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

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

自动装配JavaFX应用程序类

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

  • 将bean注入到Spring托管上下文之外的类中

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

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

该mvvmFX框架采用了类似的方法除了以上概述,以SpringBoot使用JavaFX应用程序集成:

  • 用于集成SpringBoot的mvvmFX代码。

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

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

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

其他事宜

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

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

编写此答案仅是为了提示您如何解决此问题,而不是作为有关如何将依赖项注入与JavaFX集成的通用指南,这可能会是一个棘手的问题,因此无法全面介绍。



 类似资料:
  • 有没有一种方法我可以手动注入依赖在我的按钮监听器或传递它到启动方法。 如果有解决方案,请告诉我,因为我是JavaFX的新手

  • 我有一个spring启动项目(版本2.3.3.RELEASE),它使用spring Webflux、spring数据和R2DBC。在我添加以下依赖项之前,它一直运行良好: 之后,Spring无法启动,因为它无法解析此对象的依赖关系: 错误消息如下: 如果我删除spring boot starter data redis依赖项,问题就不会发生。 我的预感是,这可能是一个依赖地狱问题,org.spri

  • 问题内容: 我试图将Spring依赖项注入到JPA EntityListener中。这是我的侦听器类: 这是我的Entity类: 但是,我的依赖项(即)始终为null。 问题答案: 注入对无状态bean的依赖关系的一种方法是将依赖关系定义为“静态”,创建一个setter方法,以便Spring可以注入依赖关系(将其分配给静态依赖关系)。 将依赖项声明为静态。 创建一个方法,以便Spring可以注入它

  • 我正在用Symfony制作简单的应用程序。我在这里配置了服务 我的服务使用存储库(例如,评论服务使用评论存储库),这里是的构造函数 性质 构造函数: 当我试图运行我的应用程序我得到这个错误 PHP致命错误:未捕获Symfony\Component\DependencyInjection\Exception\AutowiringFailedException:无法自动连线服务“AppBundle\R

  • 我必须使用Spring Quartz和JDBC Store来调度应用程序。我不确定当从数据库触发作业时如何处理依赖注入。一种方法是在作业触发后从上下文中检索bean。但不会再有了。当在JDBC Store上使用Spring Quartz进行集群时,关于如何处理DI的任何想法。