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

SpringBoot AOT结合JavaFX运行时无法找到上下文的解决方案咨询

SpringBoot 结合 JavaFX 原生编译(AOT)失败问题

我尝试将SpringBoot与JavaFX结合使用,主类继承JavaFX的Application类,并在init方法中通过JavaFX线程启动Spring上下文。这种方式在运行及构建Jar包时均正常工作,但使用native-maven-plugin执行mvn native:compile -Pnative进行原生编译时,出现如下错误:

Exception in thread "main" java.lang.IllegalStateException: No application context available after calling main method of 'com.example.JavaFxNative.problemDemo.ProblemDemoApplication'. Does it run a SpringApplication?
        at org.springframework.boot.SpringApplicationAotProcessor$AotProcessorHook.run(SpringApplicationAotProcessor.java:120)
        at org.springframework.boot.SpringApplicationAotProcessor.prepareApplicationContext(SpringApplicationAotProcessor.java:60)
        at org.springframework.context.aot.ContextAotProcessor.doProcess(ContextAotProcessor.java:83)
        at org.springframework.context.aot.ContextAotProcessor.doProcess(ContextAotProcessor.java:49)
        at org.springframework.context.aot.AbstractAotProcessor.process(AbstractAotProcessor.java:82)
        at org.springframework.boot.SpringApplicationAotProcessor.main(SpringApplicationAotProcessor.java:80)

请问是否存在可行方案,能在由JavaFX创建Spring上下文的场景下,结合使用SpringBoot AOT?

以下是可复现该问题的代码及配置文件:

主类代码

package com.example.JavaFxNative.problemDemo;

import javafx.application.Application;
import javafx.stage.Stage;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ConfigurableApplicationContext;

@SpringBootApplication
public class ProblemDemoApplication extends Application {

    protected ConfigurableApplicationContext springContext;

    public static void main(String[] args) {
        Application.launch(args);
    }

    @Override
    public void init() throws Exception {
        springContext = configurableApplicationContext();

    }

    @Override
    public void start(Stage stage) throws Exception {

        stage.show();

    }

    @Override
    public void stop() throws Exception {
        springContext.close();
    }

    private ConfigurableApplicationContext configurableApplicationContext(){
        SpringApplicationBuilder springApplicationBuilder = new SpringApplicationBuilder(ProblemDemoApplication.class);
        String[] args = getParameters().getRaw().toArray(String[]::new);
        return springApplicationBuilder.run(args);
    }
}

pom.xml 配置

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.5</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example.JavaFxNative</groupId>
    <artifactId>problemDemo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>problemDemo</name>
    <description>Demo for JavaFx and SpringBoot native</description>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-controls</artifactId>
            <version>21.0.3</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.graalvm.buildtools</groupId>
                <artifactId>native-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

module-info.java 配置

open module demo{
    requires javafx.base;
    requires javafx.controls;
    requires spring.boot;
    requires spring.boot.autoconfigure;
    requires spring.context;
}

解决方案

核心原因

SpringBoot AOT处理器期望主类直接启动SpringApplication,但当前代码中主类调用的是Application.launch(),Spring上下文在JavaFX的init()方法中启动,AOT处理器无法检测到Spring上下文的初始化过程,导致报错。

调整方案

让SpringBoot AOT能够识别Spring上下文的启动逻辑,同时保留JavaFX的生命周期控制,具体步骤如下:

  1. 拆分主类与JavaFX应用类
    创建独立的SpringBoot主类负责启动Spring上下文,JavaFX应用类作为Spring Bean由上下文管理:

    // SpringBoot主类
    package com.example.JavaFxNative.problemDemo;
    
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.builder.SpringApplicationBuilder;
    import org.springframework.context.ConfigurableApplicationContext;
    import org.springframework.context.event.ApplicationReadyEvent;
    
    @SpringBootApplication
    public class SpringBootApp {
        public static void main(String[] args) {
            ConfigurableApplicationContext context = new SpringApplicationBuilder(SpringBootApp.class)
                    .listeners(event -> {
                        if (event instanceof ApplicationReadyEvent) {
                            ApplicationContextProvider.setApplicationContext(context);
                        }
                    })
                    .run(args);
            // 启动JavaFX应用
            JavaFxApp.launch(JavaFxApp.class, args);
        }
    }
    
    // JavaFX应用类(Spring Bean)
    package com.example.JavaFxNative.problemDemo;
    
    import javafx.application.Application;
    import javafx.stage.Stage;
    import org.springframework.context.ConfigurableApplicationContext;
    import org.springframework.stereotype.Component;
    
    @Component
    public class JavaFxApp extends Application {
        private ConfigurableApplicationContext springContext;
    
        @Override
        public void init() throws Exception {
            springContext = ApplicationContextProvider.getApplicationContext();
        }
    
        @Override
        public void start(Stage stage) throws Exception {
            stage.show();
        }
    
        @Override
        public void stop() throws Exception {
            springContext.close();
        }
    }
    
    // 上下文全局提供者
    package com.example.JavaFxNative.problemDemo;
    
    import org.springframework.context.ConfigurableApplicationContext;
    
    public class ApplicationContextProvider {
        private static ConfigurableApplicationContext context;
    
        public static void setApplicationContext(ConfigurableApplicationContext ctx) {
            context = ctx;
        }
    
        public static ConfigurableApplicationContext getApplicationContext() {
            return context;
        }
    }
    
  2. 调整pom.xml配置
    指定SpringBoot主类,确保AOT处理器能正确识别:

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <mainClass>com.example.JavaFxNative.problemDemo.SpringBootApp</mainClass>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.graalvm.buildtools</groupId>
                <artifactId>native-maven-plugin</artifactId>
                <configuration>
                    <mainClass>com.example.JavaFxNative.problemDemo.SpringBootApp</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>
    
  3. 更新module-info.java
    添加Spring核心模块依赖:

    open module demo{
        requires javafx.base;
        requires javafx.controls;
        requires spring.boot;
        requires spring.boot.autoconfigure;
        requires spring.context;
        requires spring.core;
    }
    

关键说明

  • 拆分后SpringBoot主类直接启动上下文,AOT处理器可正常检测并生成原生代码。
  • JavaFX应用作为Spring Bean,生命周期由Spring和JavaFX共同管理,init()方法可直接获取上下文。
  • 该方案既保留JavaFX的UI生命周期控制,又满足SpringBoot AOT的原生编译要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 10:34:56