【发布时间】:2020-01-14 03:33:44
【问题描述】:
我在一个文本编辑器程序中使用带有 XML 配置的 Spring 来设置 bean 依赖项,在该程序中我使用 JavaFX 作为 GUI。对于文件选择器,我有一个文件管理器类,应该将应用程序的阶段注入其中。我有 2 种方法打印 Stage 对象以查看它是否为空。在init()方法中,对象打印成功,输出javafx.stage.Stage@1cdcac0e。但是当我调用open() 方法时,我得到了一个错误。
首先,这是在 Beans.xml 中配置我的 bean 的方式:
<?xml version = "1.0" encoding = "UTF-8"?>
<beans xmlns = "http://www.springframework.org/schema/beans"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation = "http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="main" class="config.Main" scope="singleton" init-method="initiate">
</bean>
<bean id = "fileManager" class="files.FileManager" scope="singleton" init-method="init">
<property name="ownerWindow" value="#{main.primaryStage}"/>
</bean>
<bean id = "editor" class = "controllers.Editor" init-method="init">
<property name="fileManager">
<bean id="fileManager" class="files.FileManager"/>
</property>
</bean>
</beans>
这是我的文件管理器类。
package files;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
public class FileManager {
Stage ownerWindow;
FileChooser fileChooser;
public void open() {
System.out.println(ownerWindow);
}
public void setOwnerWindow(Stage ownerWindow) {
this.ownerWindow = ownerWindow;
}
public void init() {
System.out.println(ownerWindow);
}
}
我的主要课程是这样的:
package config;
public class Main extends Application {
public static ApplicationContext context = new ClassPathXmlApplicationContext("/Beans.xml");
FXMLLoader loader = new FXMLLoader();
public Stage primaryStage = new Stage();
Parent root;
String rootPath = "/views/Editor.fxml";
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
root = loader.load(getClass().getResourceAsStream(rootPath));
this.primaryStage.setScene(new Scene(root));
this.primaryStage.show();
}
public void setPrimaryStage(Stage primaryStage) {
this.primaryStage = primaryStage;
}
public void initiate() {
System.out.println(primaryStage);
}
}
Main 中的 initiate() 方法与 FileManager 中的 init() 方法打印同一行,因此我假设 Spring 已将 primaryStage 成功注入到 FileManager 类中。
尽管如此,当我从第三类(即Editor 类)调用open() 时,我得到NullPointerException:
java.lang.NullPointerException
at controllers.Editor.openNewFile(Editor.java:15)
Editor 类是我的应用程序 GUI 的控制器,它有一个应该由 Spring 注入的 FileManager 实例,在它的 init() 方法中,它只是打印 FileManager 对象,程序输出 @ 987654336@,所以我假设实例已成功注入,不应为空。
我的编辑器类如下:
package controllers;
public class Editor {
//Spring bean
private FileManager fileManager;
@FXML TextArea page;
@FXML Menu menuFile;
@FXML private void openNewFile() {
fileManager.open();
}
public void setFileManager(FileManager fileManager) {
this.fileManager = fileManager;
}
public void init() {
System.out.println(fileManager);
}
}
openNewFile() 方法是引发错误的地方。
我的 fxml 文件以防万一:
<AnchorPane prefHeight="600.0" prefWidth="700.0" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="controllers.Editor">
<children>
<MenuBar layoutX="188.0" layoutY="14.0" AnchorPane.bottomAnchor="575.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<Menu fx:id="menuFile" mnemonicParsing="false" text="File">
<MenuItem text="New" onAction="#openNewFile"/>
<MenuItem text="Open"/>
<MenuItem text="Open Recent"/>
<MenuItem text="Save"/>
<MenuItem text="Save as"/>
<MenuItem text="Close"/>
</Menu>
</MenuBar>
<BorderPane layoutX="250.0" layoutY="178.0" AnchorPane.bottomAnchor="50.0" AnchorPane.leftAnchor="100.0" AnchorPane.rightAnchor="100.0" AnchorPane.topAnchor="100.0">
<center>
<AnchorPane prefHeight="550.0" prefWidth="500.0" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1">
<children>
<TextArea fx:id="page" layoutX="186.0" layoutY="100.0" wrapText="true" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<padding>
<Insets right="10.0" />
</padding>
</TextArea>
</children>
</AnchorPane>
</center>
</BorderPane>
</children>
</AnchorPane>
【问题讨论】:
-
您有 2 个
FileManager实例。一个有依赖另一个没有。您应该引用第一个FileManager而不是创建一个新的。 -
您的 NPE 表明导致 NPE 的
Editor实例不是由 Spring 创建的。你能告诉我们你是如何获得Editor实例的吗? (尽管如此,您还创建了 2 个FileManager实例;在editor定义上使用<property name="fileManager" ref="fileManager"/>) -
@M.Deinum 我删除了第二个
FileManager(编辑器 bean 内部的那个),但我仍然得到相同的结果 -
删除它不会有帮助,因为这会使它为空,你必须把对顶层的引用放在那里。在
Beans.xml中定义一些东西并不意味着它是Java-FX 使用的实例,我怀疑你需要做更多的事情才能进行适当的集成。 -
JavaFX 正在控制您的实例,而不是 Spring。所以用 Spring 定义它并且没有 Spring 控制它不会真正起作用。
标签: java spring dependency-injection nullpointerexception