You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

启动应用后Repository始终为null的Spring+JavaFX问题求助

Spring整合JavaFX时Repository注入为null触发空指针异常

我正在开发一个Java应用:前端用JavaFX实现登录凭证录入,后台通过ChromeDriver完成自动登录,基于Spring框架整合H2数据库存储邮箱和密码。但启动应用后Repository始终为null,调用时触发NullPointerException,尝试过构造器级、Setter级、字段级三种依赖注入方式,问题仍未解决。

相关代码

MBA实体类

@Entity
@Getter
public class MBA {

    @Id
    private UUID id;
    private String email;
    private String password;
    
    public static WebDriver driver;
    private static int amountOfSales;
    
    public MBA() {
        this.id = UUID.randomUUID();
        this.email = null;
        this.password = null;
    }
    
    public MBA(String email, String password) {
        this.id = UUID.randomUUID();
        this.email = email;
        this.password = password;
    }
}

MBAApplicationService服务类

@Service
public class MBAApplicationService {

    public static WebDriver driver;
    private static int amountOfSales;
    
    private final MBARepository mbaRepository;
    
    public MBAApplicationService(MBARepository mbaRepository) {
        this.mbaRepository = mbaRepository;
    }
    
    public void saveLogin(String email, String password) {
        MBA mba = new MBA(email, password);
        mbaRepository.save(mba);
    }
    
    public void chromeDriverSetUp() {
        System.setProperty("webdriver.chrome.driver", "C:\\Program Files (x86)\\chromedriver.exe");
        driver = new ChromeDriver();
        driver.manage().window().maximize();
    }
}

MBARepository数据访问接口

@Repository
public interface MBARepository extends CrudRepository<MBA, UUID> {

}

JavaFX控制器类

@Service
public class Controller {

    @FXML private Label mainSceneLabel;
    @FXML private Label loginsSceneLabel;
    @FXML private Label sellerSceneLabel;
    @FXML private TextField emailMBA;
    @FXML private PasswordField passwordMBA;
    @FXML private Label mbaAmountOfSales;
    private Stage stage;
    private Scene scene;
    private Parent root;
    
    @Autowired
    private MBARepository mbaRepository;
    
    @FXML
    public void openLoginScene() throws IOException {
        Parent root = FXMLLoader.load(getClass().getResource("LoginsScene.fxml"));
        stage = (Stage)(mainSceneLabel.getScene().getWindow());
        scene = new Scene(root);
        stage.setScene(scene);
        stage.show();
    }
    
    @FXML
    public void openMainScene() throws IOException {
        Parent root = FXMLLoader.load(getClass().getResource("1_MainScene.fxml"));
        stage = (Stage)(loginsSceneLabel.getScene().getWindow());
        scene = new Scene(root);
        stage.setScene(scene);
        stage.show();
    }
    
    @FXML
    public void switchToSellerViewScene() throws IOException {
        Parent root = FXMLLoader.load(getClass().getResource("SellerViewScene.fxml"));
        stage = (Stage)(mainSceneLabel.getScene().getWindow());
        scene = new Scene(root);
        stage.setScene(scene);
        stage.show();
    }
    
    public void saveLogins() {
        String emailAmazon = emailMBA.getText();
        String passwordAmazon = passwordMBA.getText();
        MBAApplicationService mbaApplicationService = new MBAApplicationService(mbaRepository);
        mbaApplicationService.saveLogin(emailAmazon, passwordAmazon);
    }
}

报错信息

Caused by: java.lang.NullPointerException: Cannot invoke "mba.MBARepository.save(Object)" because "this.mbaRepository" is null 
at com.example.moduleinfo/mba.MBAApplicationService.saveLogin(MBAApplicationService.java:58)
at com.example.moduleinfo/com.example.moduleinfo.Controller.saveLogins(Controller.java:85)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
... 53 more

问题根源

  1. JavaFX控制器实例不由Spring管理:默认情况下FXMLLoader会自行实例化控制器,不会从Spring容器获取,导致@Autowired的mbaRepository无法被注入,始终为null。
  2. 手动创建Service实例:在saveLogins中手动new MBAApplicationService(mbaRepository),但此时mbaRepository本身就是null,传递后自然还是触发空指针。

解决方案

1. 让Spring接管JavaFX控制器的实例化

修改控制器中的页面加载方法,使用Spring的ApplicationContext作为FXMLLoader的控制器工厂,确保控制器由Spring创建并注入依赖:

@Autowired
private ApplicationContext context;

@FXML
public void openLoginScene() throws IOException {
    FXMLLoader loader = new FXMLLoader(getClass().getResource("LoginsScene.fxml"));
    // 设置Spring容器为控制器工厂
    loader.setControllerFactory(context::getBean);
    Parent root = loader.load();
    stage = (Stage)(mainSceneLabel.getScene().getWindow());
    scene = new Scene(root);
    stage.setScene(scene);
    stage.show();
}

同时保留Controller类上的@Service注解,确保Spring能扫描并管理该Bean。

2. 注入MBAApplicationService而非手动实例化

在Controller中直接注入MBAApplicationService,由Spring负责依赖注入:

@Autowired
private MBAApplicationService mbaApplicationService;

// 修改saveLogins方法
public void saveLogins() {
    String emailAmazon = emailMBA.getText();
    String passwordAmazon = passwordMBA.getText();
    mbaApplicationService.saveLogin(emailAmazon, passwordAmazon);
}

3. 调整Spring主类的扫描范围

确保Spring Boot主类的@SpringBootApplication或@ComponentScan能覆盖Controller、Service、Repository所在的包,比如:

@SpringBootApplication(scanBasePackages = {"com.example.moduleinfo", "mba"})
public class YourApplication {
    public static void main(String[] args) {
        // 启动Spring容器
        ConfigurableApplicationContext context = SpringApplication.run(YourApplication.class, args);
        // 启动JavaFX应用
        launch(YourJavaFXApp.class, args);
    }
}

4. 优化实体类(可选)

给MBA类添加@Setter注解(Lombok),确保Spring Data JPA能正常处理实体字段的修改:

@Entity
@Getter
@Setter
public class MBA {
    // 原有代码不变
}

内容的提问来源于stack exchange,提问作者Maik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 22:50:31