【问题标题】:Spring Bean gives NullPointerException but is not nullSpring Bean 给出 NullPointerException 但不为空
【发布时间】: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 定义上使用 &lt;property name="fileManager" ref="fileManager"/&gt;
  • @M.Deinum 我删除了第二个 FileManager(编辑器 bean 内部的那个),但我仍然得到相同的结果
  • 删除它不会有帮助,因为这会使它为空,你必须把对顶层的引用放在那里。在Beans.xml 中定义一些东西并不意味着它是Java-FX 使用的实例,我怀疑你需要做更多的事情才能进行适当的集成。
  • JavaFX 正在控制您的实例,而不是 Spring。所以用 Spring 定义它并且没有 Spring 控制它不会真正起作用。

标签: java spring dependency-injection nullpointerexception


【解决方案1】:

正如@Simon 和@M 所指出的。 Deinum,NullPointerException 被抛出是因为 Spring 创建的Editor 实例不是调用openNewFile() 方法的实例,而是JavaFX 是控制我的实例的实例。使用loader.setController(context.getBean("editor)) 设置JavaFX 控制器,而不是在fxml 文件中设置它解决了我的问题。 Main 类的 start() 方法现在看起来像这样:

public void start(Stage primaryStage) throws Exception {
    loader.setController(context.getBean("editor"));
    root = loader.load(getClass().getResourceAsStream(rootPath));
    this.primaryStage.setScene(new Scene(root));
    this.primaryStage.show();

}

【讨论】:

    猜你喜欢
    • 2018-07-15
    • 1970-01-01
    • 2017-08-08
    • 1970-01-01
    • 1970-01-01
    • 2015-01-11
    • 2021-01-21
    • 2010-12-04
    • 2019-05-23
    相关资源
    最近更新 更多