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的生命周期控制,具体步骤如下:
拆分主类与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; } }调整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>更新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
相关产品推荐
相关产品推荐

