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

JavaFX Controller中@Autowire注入Spring Boot Service始终为null问题排查

问题:Spring Boot + JavaFX 中Controller注入Service报NullPointerException

我正在开发基于Spring Boot和JavaFX的应用,需将邮箱与密码存储至H2数据库。已通过JUnit测试验证数据库正常运行且可访问Spring Boot Repository,但在JavaFX Controller中通过@Autowire注入Spring Boot Service时出现NullPointerException,无法通过GUI调用业务逻辑。

相关代码

JavaFXController

@Component
@FxmlView("start.fxml")
@Service
public class JavaFXController {

    @FXML private Label startLabel;
    @FXML private Label settingsLabel;
    @FXML private TextField emailAmazonMerchOnDemand;
    @FXML private PasswordField passwordAmazonMerchOnDemand;

    private Stage stage;
    private Scene scene;

    @Autowired
    private AmazonMerchOnDemandService amazonMerchOnDemandService;

    @FXML
    public void openSettingsSceneFromStartScene() throws IOException {
        Parent root = FXMLLoader.load(getClass().getClassLoader().getResource("settings.fxml"));
        stage = (Stage)(startLabel.getScene().getWindow());
        scene = new Scene(root);
        stage.setScene(scene);
        stage.show();
    }

    @FXML
    public void saveLogins() {
        String emailAmazon = emailAmazonMerchOnDemand.getText();
        String passwordAmazon = passwordAmazonMerchOnDemand.getText();
        AmazonMerchOnDemand amazonMerchOnDemandLogin = new AmazonMerchOnDemand();
        amazonMerchOnDemandLogin.setId(1L);
        amazonMerchOnDemandLogin.setEmail(emailAmazon);
        amazonMerchOnDemandLogin.setPassword(passwordAmazon);
        amazonMerchOnDemandService.saveLogin(amazonMerchOnDemandLogin);
    }
}

JavaFXApplication

@SpringBootApplication
public class JavaFXApplication extends Application {
    private ConfigurableApplicationContext applicationContext;

    @Override
    public void init() throws Exception {
        String[] args = getParameters().getRaw().toArray(new String[0]);
        this.applicationContext = new SpringApplicationBuilder().sources(PrintOnDemandSellerViewApplication.class).run(args);
    }

    @Override
    public void start(Stage stage) throws Exception {
        FXMLLoader loader = new FXMLLoader();
        URL xmlUrl = getClass().getClassLoader().getResource("start.fxml");
        loader.setLocation(xmlUrl);
        loader.setController(applicationContext.getBean(JavaFXController.class));
        Parent root = loader.load();
        Scene scene = new Scene(root);
        stage.setScene(scene);
        stage.show();
    }

    @Override
    public void stop() throws Exception {
        this.applicationContext.close();
        Platform.exit();
    }
}

AmazonMerchOnDemandService

@Service
@Component
public class AmazonMerchOnDemandService {

    public static WebDriver driver;
    private static int amountOfSales;

    @Autowired
    private AmazonMerchOnDemandRepository amazonMerchOnDemandRepository;

    public void saveLogin(AmazonMerchOnDemand amazonMerchOnDemand) {
        amazonMerchOnDemandRepository.save(amazonMerchOnDemand);
    }

    public void chromeDriverSetUp() {
        System.setProperty("webdriver.chrome.driver", "C:\Program Files (x86)\chromedriver.exe");
        driver = new ChromeDriver();
        driver.manage().window().maximize();
    }

    public void login() {
        String email = amazonMerchOnDemandRepository.findById(1L).get().getEmail();
        System.out.println("Email: " + email);
        String password = amazonMerchOnDemandRepository.findById(1L).get().getPassword();
        System.out.println("Password: " + password);
}
}

AmazonMerchOnDemandRepository

@Repository
public interface AmazonMerchOnDemandRepository extends CrudRepository <AmazonMerchOnDemand, Long> {
}

PrintOnDemandSellerViewApplicationTests

@SpringBootTest(classes = JavaFXApplication.class)
class PrintOnDemandSellerViewApplicationTests {

    @Autowired
    private AmazonMerchOnDemandRepository amazonMerchOnDemandRepository;
    @Autowired
    private AmazonMerchOnDemandSampleData amazonMerchOnDemandSampleData;

    @BeforeEach
    public void setupData() {
        amazonMerchOnDemandSampleData.createAmazonMerchOnDemandLogin();
    }

    @Test
    public void testHasAmazonMerchOnDemandLoginRightPasswordAndRightEmail() {
        assertTrue(amazonMerchOnDemandRepository.existsById(1L));
        Optional<AmazonMerchOnDemand> amazonMerchOnDemandOptional = amazonMerchOnDemandRepository.findById(1L);
        assertFalse(amazonMerchOnDemandOptional.isEmpty());
        AmazonMerchOnDemand amazonMerchOnDemandLogin = amazonMerchOnDemandOptional.get();
        assertEquals("password", amazonMerchOnDemandLogin.getPassword());
        assertEquals("test@gmail.com", amazonMerchOnDemandLogin.getEmail());
    }

}

异常信息

Caused by: java.lang.reflect.InvocationTargetException
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at com.sun.javafx.reflect.Trampoline.invoke(MethodUtil.java:77)
    at jdk.internal.reflect.GeneratedMethodAccessor37.invoke(Unknown Source)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at javafx.base@19/com.sun.javafx.reflect.MethodUtil.invoke(MethodUtil.java:275)
    at javafx.fxml@19/com.sun.javafx.fxml.MethodHelper.invoke(MethodHelper.java:84)
    at javafx.fxml@19/javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1854)
    ... 29 more
Caused by: java.lang.NullPointerException
    at com.example.printondemandsellerview.JavaFXController.saveLogins(JavaFXController.java:53)
    ... 40 more

排查建议

  • 检查start.fxml中是否存在fx:controller属性,若有必须删除。因为你已通过loader.setController(applicationContext.getBean(JavaFXController.class))手动指定Spring管理的Controller实例,FXML文件中再指定会导致FXMLLoader创建新的非Spring管理实例,该实例的amazonMerchOnDemandService会为null。
  • 清理冗余注解:JavaFXController同时标注了@Component、@FxmlView、@Service,仅保留@Component或@Service其中一个即可,避免Spring重复创建实例。
  • 简化AmazonMerchOnDemandService注解:同时标注@Service和@Component,保留@Service即可。
  • 验证Spring上下文加载情况:在JavaFXApplication的start方法中打印applicationContext.getBean(JavaFXController.class).amazonMerchOnDemandService,确认Spring是否完成注入。
  • 修正场景加载方式:若settings.fxml对应的Controller也需要Spring注入,不能使用FXMLLoader.load()静态方法,需像加载start.fxml一样从Spring上下文获取Controller实例并设置给FXMLLoader,否则新场景的Controller会是非Spring管理实例。
  • 确认主启动类正确性:检查JavaFXApplication的init方法中SpringApplicationBuilder.sources()传入的PrintOnDemandSellerViewApplication是否为正确的主启动类,避免Spring扫描范围错误导致Bean未加载。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 04:45:46