启动应用后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
问题根源
- JavaFX控制器实例不由Spring管理:默认情况下FXMLLoader会自行实例化控制器,不会从Spring容器获取,导致
@Autowired的mbaRepository无法被注入,始终为null。 - 手动创建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
相关产品推荐
相关产品推荐

