Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/339.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java @Value和@Autowired上的NPE_Java_Spring_Javafx - Fatal编程技术网

Java @Value和@Autowired上的NPE

Java @Value和@Autowired上的NPE,java,spring,javafx,Java,Spring,Javafx,我有一个javafx+spring应用程序 应用程序侦听串行端口,读取数据并将其显示到UI。 outputLoggerFile上的控制器类和同一类上的serialPort由NPE引起的问题 这是我的带有PropertySource的配置文件,因此我的环境应该知道这些属性。 SpringConfig @Configuration @PropertySource({"classpath:com.properties", "classpath:application.properties"}) @Co

我有一个javafx+spring应用程序

应用程序侦听串行端口,读取数据并将其显示到UI。 outputLoggerFile上的控制器类和同一类上的serialPort由NPE引起的问题

这是我的带有PropertySource的配置文件,因此我的环境应该知道这些属性。 SpringConfig

@Configuration
@PropertySource({"classpath:com.properties", "classpath:application.properties"})
@ComponentScan
public class SpringConfig {

    @Bean
    public SerialPort serialPort(@Value("${serialPort.portName}") String portName){
        return new SerialPort(portName);
    }

    @Bean
    public AnnotationMBeanExporter annotationMBeanExporter(){
        AnnotationMBeanExporter annotationMBeanExporter = new AnnotationMBeanExporter();
        annotationMBeanExporter.addExcludedBean("dataSource");
        return annotationMBeanExporter;
    }
}
这个类将我的属性设置为SerialPort对象,注入EventListener类和openning连接。很好。 ComReader

@Scope("singletone")
@Component
public class ComReader {

    @Autowired
    private EventListener eventListener;

    @Autowired
    public SerialPort serialPort;

    @Value("${serialPort.baudRate}")
    private int baudRate;
    @Value("${serialPort.dataBits}")
    private int dataBits;
    @Value("${serialPort.stopBits}")
    private int stopBits;
    @Value("${serialPort.parity}")
    private int parity;

    @PostConstruct
    public void init(){
        try {
            System.out.println("Opening port: " + serialPort.getPortName());
            serialPort.openPort();
            serialPort.setParams(baudRate,dataBits,stopBits,parity);
            serialPort.addEventListener(eventListener, 1);
        } catch (SerialPortException e) {
            e.printStackTrace();
        }
    }
}
@org.springframework.stereotype.Controller
public class Controller {

    @Value("${logger.outputFilePath}")
    private String outputLoggerFile;

    private SerialPort serialPort;

    @Autowired
    public void setSerialPort(SerialPort serialPort) {
        this.serialPort = serialPort;
    }


    private static ObservableList<CallDetailRecord> list = FXCollections.observableArrayList();


    @FXML
    void initialize(){

        Timer scheduler = new Timer();
        scheduler.schedule(new TimerTask() {
            @Override
            public void run() {
                if (serialPort.isOpened()) circlePortStatus.setFill(Color.GREEN); //(NPE HERE)
                else circlePortStatus.setFill(Color.RED);
            }
        }, 5_000, 60_000);





        counterCol.setCellValueFactory(new PropertyValueFactory<>("id"));
        startTimeCol.setCellValueFactory(new PropertyValueFactory<>("startTime"));
        stopTimeCol.setCellValueFactory(new PropertyValueFactory<>("stopTime"));
        numberACol.setCellValueFactory(new PropertyValueFactory<>("numberB"));
        numberBCol.setCellValueFactory(new PropertyValueFactory<>("numberA"));
        rescodeCol.setCellValueFactory(new PropertyValueFactory<>("resultCode"));
        subACol.setCellValueFactory(new PropertyValueFactory<>("subscriberB"));
        subBCol.setCellValueFactory(new PropertyValueFactory<>("subscriberA"));
        table.setItems(list);

        Label webLinkLabel = new Label("Веб ресурс");
        AppStart appStart = new AppStart();
        webLinkLabel.setOnMouseClicked(event -> appStart.getHostServices().showDocument(getURLPropertie()));
        webLink.setGraphic(webLinkLabel);

        Label logsLinkLabel = new Label("Логи");
        logsLinkLabel.setOnMouseClicked(event -> appStart.getHostServices().showDocument(outputLoggerFile));   //(NPE HERE)
        logsLink.setGraphic(logsLinkLabel);

    }

    public void addCdr(CallDetailRecord cdr){
        list.add(cdr);
        list.sort(Comparator.comparingInt(CallDetailRecord::getId).reversed());
    }

    private String getURLPropertie(){
        try(InputStream is = new FileInputStream(Objects.requireNonNull(getClass().getClassLoader().getResource("application.properties")).getFile())){
            Properties prop = new Properties();
            prop.load(is);
            return prop.getProperty("url.link");
        } catch (IOException  e) {
            e.printStackTrace();
        }
        return "https://google.com";
    }
}
问题类一切正常,除了我想在这里注入的任何类/字段

控制器

@Scope("singletone")
@Component
public class ComReader {

    @Autowired
    private EventListener eventListener;

    @Autowired
    public SerialPort serialPort;

    @Value("${serialPort.baudRate}")
    private int baudRate;
    @Value("${serialPort.dataBits}")
    private int dataBits;
    @Value("${serialPort.stopBits}")
    private int stopBits;
    @Value("${serialPort.parity}")
    private int parity;

    @PostConstruct
    public void init(){
        try {
            System.out.println("Opening port: " + serialPort.getPortName());
            serialPort.openPort();
            serialPort.setParams(baudRate,dataBits,stopBits,parity);
            serialPort.addEventListener(eventListener, 1);
        } catch (SerialPortException e) {
            e.printStackTrace();
        }
    }
}
@org.springframework.stereotype.Controller
public class Controller {

    @Value("${logger.outputFilePath}")
    private String outputLoggerFile;

    private SerialPort serialPort;

    @Autowired
    public void setSerialPort(SerialPort serialPort) {
        this.serialPort = serialPort;
    }


    private static ObservableList<CallDetailRecord> list = FXCollections.observableArrayList();


    @FXML
    void initialize(){

        Timer scheduler = new Timer();
        scheduler.schedule(new TimerTask() {
            @Override
            public void run() {
                if (serialPort.isOpened()) circlePortStatus.setFill(Color.GREEN); //(NPE HERE)
                else circlePortStatus.setFill(Color.RED);
            }
        }, 5_000, 60_000);





        counterCol.setCellValueFactory(new PropertyValueFactory<>("id"));
        startTimeCol.setCellValueFactory(new PropertyValueFactory<>("startTime"));
        stopTimeCol.setCellValueFactory(new PropertyValueFactory<>("stopTime"));
        numberACol.setCellValueFactory(new PropertyValueFactory<>("numberB"));
        numberBCol.setCellValueFactory(new PropertyValueFactory<>("numberA"));
        rescodeCol.setCellValueFactory(new PropertyValueFactory<>("resultCode"));
        subACol.setCellValueFactory(new PropertyValueFactory<>("subscriberB"));
        subBCol.setCellValueFactory(new PropertyValueFactory<>("subscriberA"));
        table.setItems(list);

        Label webLinkLabel = new Label("Веб ресурс");
        AppStart appStart = new AppStart();
        webLinkLabel.setOnMouseClicked(event -> appStart.getHostServices().showDocument(getURLPropertie()));
        webLink.setGraphic(webLinkLabel);

        Label logsLinkLabel = new Label("Логи");
        logsLinkLabel.setOnMouseClicked(event -> appStart.getHostServices().showDocument(outputLoggerFile));   //(NPE HERE)
        logsLink.setGraphic(logsLinkLabel);

    }

    public void addCdr(CallDetailRecord cdr){
        list.add(cdr);
        list.sort(Comparator.comparingInt(CallDetailRecord::getId).reversed());
    }

    private String getURLPropertie(){
        try(InputStream is = new FileInputStream(Objects.requireNonNull(getClass().getClassLoader().getResource("application.properties")).getFile())){
            Properties prop = new Properties();
            prop.load(is);
            return prop.getProperty("url.link");
        } catch (IOException  e) {
            e.printStackTrace();
        }
        return "https://google.com";
    }
}
如果我试图在另一个类中调试,使用它的控制器显示变量outputLoggerFile包含我的属性。我不知道为什么


sources-

FXMLLoader的默认行为是通过实例化FXML文件的
fx:controller
属性中指定的类来创建控制器(调用其无参数构造函数);然后,它将
@FXML
-注释字段注入控制器,并在解析FXML文件后,调用
initialize()
方法(如果有)

由于控制器是通过直接调用其构造函数来实例化的,因此Spring应用程序上下文对其一无所知,并且不能将任何
@Autowired
bean注入其中

要解决此问题,需要在
FXMLLoader
上设置一个
controllerFactory
,指示它从Spring
ApplicationContext
中“创建”(真正检索)控制器实例。控制器工厂基本上只是一个函数(一个
@functioninterface
),它接受一个
,并生成一个对象。由于这正是其中一个
ApplicationContext.getBean()
方法的签名,因此其代码如下所示:

FXMLLoader loader = new FXMLLoader(getClass().getResource("/primal.fxml"));
loader.setControllerFactory(context::getBean);
Parent root = loader.load();
其中
context
是Spring
ApplicationContext
(在加载FXML文件的方法中,您可能需要跳过一些限制来获取对它的引用;通常只是为它创建一个字段并注释该字段
自动连线
起作用)

我还将对控制器类的配置进行一些调整。默认情况下,Spring将bean作为单例范围进行管理。这绝对不是您想要的:如果您第二次加载相同的FXML,您将需要一个不同的控制器实例(因为您将拥有一组不同的UI控件)。因此,您肯定需要将控制器作为原型来确定范围

其次,Spring
@Controller
原型是为Spring MVC意义上的控制器设计的;所以我不认为这真的是你想要的(尽管我不认为这有什么坏处)。我将控制器类注释为

@Component
@Scope(BeanDefinition.PROTOTYPE_SCOPE)
public class Controller { /* ... */ }

您确定spring应用程序上下文(bean factory)正在管理您的
控制器
实例吗?您能否显示配置FXMLLoader来执行此操作的代码?
this.primaryStage=primaryStage
Platform.setImplicitExit(false)
Parent root=fxmloader.load(getClass().getResource(“/primal.fxml”)
primaryStage.setTitle(“NIIAR”)`primaryStage.getIcons().add(新图像(“/icon.png”);`<代码>primaryStage.setScene(新场景(root,1400900))
createTray()
primaryStage.show()我想不是。但是我的控制器是管理UI的,用经典的方法来注释这个控制器是行不通的?真的很感激