我有一个Java FX基本应用程序,它具有一个简单的Scene(窗体)。我有一个Mysql Db,并且正在使用Spring JPA(spring数据jpa,即存储库/实体)与之交互。
现在,由于我们知道javaFx具有一些生命周期挂钩,即:在里面()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应用程序集成的教程的示例:
该示例的关键部分是应用程序的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:
setControllerFactory()
您还需要在您希望控制器使用的任何Spring依赖项中将类注释为Spring fxmlLoader.setControllerFactory(springContext::getBean);
和@Component
。这样,FXMLLoader将注入基于@FXML的对UI元素的引用,还将委派给spring上下文以注入Spring依赖项。
@Autowired
注意,Spring有一个@Component
public class DemoController {
@FXML
private Label usernameLabel;
@Autowired
public void mySpringService;
public void initialize() {
usernameLabel.setText(
mySpringService.getLoggedInUsername()
);
}
}
注释,该注释可用于注释JavaFX控制器而不是@Controller
注释,但我建议避免为此目的使用@Component
,而应使用@Controller
注释Spring REST服务端点控制器定义。
Spring Boot应用程序和JavaFX应用程序之间的关注点分离
您可能要注意的一件事是,运行SpringBoot应用程序,生成该应用程序的新实例,并且您已经有JavaFX系统启动的JavaFX应用程序实例,因此,如果SpringBoot应用程序和JavaFX应用程序基于相同的类(如上所示),这可能会造成混淆。
因此,最好将Spring应用程序和JavaFX应用程序分开。这增强了应用程序的UI和服务部分之间关注点的分离,并使得测试变得更加容易,因为可以独立于启动和关闭JavaFX应用程序而对Spring应用程序进行单元测试。
自动装配JavaFX应用程序类
注意,使用上述设置,它将不会自动装配JavaFX应用程序类实例化实例。如果您希望这样做,可以使用以下所示的技术将Java Bean实例化的应用程序类中的bean注入:
@Controller
将以下代码放入应用程序的init方法内:
Injecting beans into a class outside the Spring managed context
[springContext
.getAutowireCapableBeanFactory()
.autowireBeanProperties(
this,
AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE,
true
);
使用与上述类似的方法将SpringBoot与JavaFX应用程序集成:
将命令行参数从JavaFX传递到SpringBoot
要将参数从JavaFX应用程序传递到SpringBoot应用程序,请使用:
mvvmFX code for integrating SpringBoot
其他问题
如果需要,甚至可以更多地控制SpringApplication的启动,可以使用SpringApplicationBuilder例如:
SpringApplication.run(
DemoApplication.class,
getParameters().getRaw().toArray(new String[0])
);
此答案只是为了提示您如何解决此问题,而不是作为有关如何将依赖项注入与JavaFX集成的通用指南,这可能会是一个棘手的问题,因此无法全面介绍。