我有问题。 这是我的主要内容:
@SpringBootApplication
public class MyAppSpringApplication extends Application {
public static ConfigurableApplicationContext springContext;
private FXMLLoader fxmlLoader;
public static void main(String[] args) {
Application.launch(args);
}
@Override
public void start(Stage stage) throws Exception {
fxmlLoader.setLocation(getClass().getResource("/sample.fxml"));
Parent root = fxmlLoader.load();
stage.setTitle("Sample app");
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
@Override
public void stop() throws Exception {
springContext.stop();
}
@Override
public void init() throws Exception {
springContext = SpringApplication.run(MyAppSpringApplication.class);
fxmlLoader = new FXMLLoader();
fxmlLoader.setControllerFactory(springContext::getBean);
}
}
我的第一个窗口(sample.fxml)与samplecontroller和sampleservice工作正常。但是我用他们的控制器和服务创建了另一个
dish-builder.fxml
,但是当我尝试在那里使用我的服务时,它不起作用,因为在dishbuilderservice中为空(albo在新控制器中不起作用sampleservice)。我听说我也应该使用它:
public static ConfigurableApplicationContext springContext;
但我不知道应该如何使用它。抱歉我的知识和英语很薄弱。
@Controller
public class DishBuilderController implements Initializable {
@Autowired
DishBuilderService dishBuilderService;
@Autowired
SampleService sampleService;
private void somefun(){
sampleService.somefunInService(); //here sampleService and
every other service has null.
}
这是我打开新的菜肴构建器窗口(位于 SampleController 中)的时刻:
@FXML
void addNoweOknoClicked(ActionEvent event) {
try {
Stage stage = (Stage)anchorPane.getScene().getWindow();
FXMLLoader fxmlLoader = new FXMLLoader();
fxmlLoader.setLocation(getClass().getResource("/dish-builder.fxml"));
AnchorPane root = fxmlLoader.load();
stage.setTitle("Sample app");
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}catch (IOException e){
e.printStackTrace();
}
}
加载
dish-builder.fxml
时,您并未在 FXMLLoader
上设置控制器工厂。这意味着 FXMLLoader
只是通过调用其无参数构造函数来创建控制器。由于控制器不是 spring 管理的 bean,因此 spring 无法向其中注入任何组件。
您需要设置控制器工厂,就像加载
sample.fxml
时所做的那样,以便 FXMLLoader
会要求 Spring 从应用程序上下文中检索控制器。
有几点与您的问题并不严格相关:
ApplicationContext
公开为公共静态字段。您可以将其注入到任何需要访问它的 spring 管理的 bean 中FXMLLoader
。 因此,将 FXMLLoader
作为实例变量是没有意义的。@Controller
注释适用于 Spring MVC 应用程序中的web控制器。它们与 JavaFX 意义上的控制器有很大不同。您应该对 JavaFX 控制器使用通用 @Component
注释。PROTOTYPE
范围,而不是默认的 SINGLETON
范围。所以你需要:
@SpringBootApplication
public class MyAppSpringApplication extends Application {
private ConfigurableApplicationContext springContext;
public static void main(String[] args) {
Application.launch(args);
}
@Override
public void start(Stage stage) throws Exception {
FXMLLoader fxmlLoader = new FXMLLoader();
fxmlLoader.setControllerFactory(springContext::getBean);
fxmlLoader.setLocation(getClass().getResource("/sample.fxml"));
Parent root = fxmlLoader.load();
stage.setTitle("Sample app");
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
@Override
public void stop() throws Exception {
springContext.stop();
}
@Override
public void init() throws Exception {
springContext = SpringApplication.run(MyAppSpringApplication.class);
}
}
那么你的
SampleController
应该看起来像
@Component
@Scope("prototype")
public class SampleController {
@Autowired
private ConfigurableApplicationContext springContext ;
@FXML
void addNoweOknoClicked(ActionEvent event) {
try {
Stage stage = (Stage)anchorPane.getScene().getWindow();
FXMLLoader fxmlLoader = new FXMLLoader();
fxmlLoader.setControllerFactory(springContext::getBean);
fxmlLoader.setLocation(getClass().getResource("/dish-builder.fxml"));
AnchorPane root = fxmlLoader.load();
stage.setTitle("Sample app");
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}catch (IOException e){
e.printStackTrace();
}
}
}
同样
@Component
@Scope("prototype")
public class DishBuilderController implements Initializable {
@Autowired
DishBuilderService dishBuilderService;
@Autowired
SampleService sampleService;
private void somefun(){
// this should now work, since the controller is managed by Spring:
sampleService.somefunInService();
}
}
补充:这里有两个现成的模板,包含 JavaFX、Spring Boot 和 Maven/Gradle。
我将感谢 GitHub 上的明星支持它的免费开源,从而帮助您解决问题。 <3
https://github.com/davidweber411/javafx-JavaFxSpringBootGradleApp
https://github.com/davidweber411/javafx-JavaFxSpringBootMavenApp