我正在尝试在 javaFX 应用程序中使用 SpringBoot。我使用 javafx-weaver-spring-boot-starter,它与 java 配合得很好 < 9, but there are some problems with java 9+ (modularity).
My project structure:
应用程序启动代码:
package test;
import javafx.application.Application;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class AppStarter {
public static void main(String[] args) {
Application.launch(JavaFxApplication.class, args);`
}
}
JavaFx应用程序代码:
package test;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import net.rgielen.fxweaver.core.FxWeaver;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ConfigurableApplicationContext;
public class JavaFxApplication extends Application {
private ConfigurableApplicationContext applicationContext;
@Override
public void init() {
String[] args = getParameters().getRaw().toArray(new String[0]);
this.applicationContext = new SpringApplicationBuilder()
.sources(AppStarter.class)
.run(args);
}
@Override
public void start(Stage stage) {
FxWeaver fxWeaver = applicationContext.getBean(FxWeaver.class);
Parent root = fxWeaver.loadView(MyController.class);
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
@Override
public void stop() {
this.applicationContext.close();
Platform.exit();
}
}
我的控制器代码:
package test;
import javafx.event.ActionEvent;
import net.rgielen.fxweaver.core.FxmlView;
import org.springframework.stereotype.Component;
@Component
@FxmlView("hello-view.fxml")
public class MyController {
public void onHelloButtonClick(ActionEvent actionEvent) {
System.out.println("Hello World");
}
}
modules-info.java:
module test {
requires spring.boot.autoconfigure;
requires javafx.graphics;
requires spring.context;
requires net.rgielen.fxweaver.core;
requires spring.boot;
requires javafx.weaver.spring.boot.starter;
requires net.rgielen.fxweaver.spring.boot.autoconfigure;
requires net.rgielen.fxweaver.spring;
exports test;
opens test;
}
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>2.6.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo2</name>
<description>demo2</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>net.rgielen</groupId>
<artifactId>javafx-weaver-spring-boot-starter</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>17-ea+11</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>17-ea+11</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>17</source>
<target>17</target>
</configuration>
</plugin>
</plugins>
</build>
</project>1
当我尝试运行该应用程序时,出现以下异常:
....
Caused by: java.lang.IllegalAccessError: class test.AppStarter$$EnhancerBySpringCGLIB$$e15856c4 (in module test) cannot access class org.springframework.cglib.core.ReflectUtils (in unnamed module @0x4fb0f9) because module test does not read unnamed module @0x4fb0f9
at test/test.AppStarter$$EnhancerBySpringCGLIB$$e15856c4.CGLIB$STATICHOOK1(<generated>)
at test/test.AppStarter$$EnhancerBySpringCGLIB$$e15856c4.<clinit>(<generated>)
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:467)
at org.springframework.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:593)
at org.springframework.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:363)
at org.springframework.cglib.proxy.Enhancer.generate(Enhancer.java:585)
at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:110)
at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:108)
at org.springframework.cglib.core.internal.LoadingCache$2.call(LoadingCache.java:54)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at org.springframework.cglib.core.internal.LoadingCache.createEntry(LoadingCache.java:61)
... 21 more
...
模块测试不读取未命名的模块... 我该如何修复它?
Spring 5 与 JavaFX 平台模块系统不友好
Spring 不会真正为模块构建,直到 Spring 6/Springboot 3 发布。
Spring Framework 6 确实有望为所有核心框架模块引入模块信息描述符,对核心 Java 模块所需的依赖性最小,从而使 JDK 的 jlink 工具能够为 Spring 设置构建自定义运行时映像。可选的第三方库和某些配置策略可能会受到限制,因此目前还不清楚这种显式模块的使用在 Spring 用户中会变得多么流行。
对于基于 Spring 5 的应用程序,该框架不容易与 Java 平台模块系统兼容。
所以我不建议尝试构建依赖于 Spring 的模块化 JavaFX 应用程序,直到:
Spring 6/SpringBoot 3 发布,
并且
您使用的依赖库也可以轻松兼容Java模块系统。
module-info.java
时。如何使您的项目非模块化
但是,您今天仍然可以构建依赖于 Spring 5 的 JavaFX 17 应用程序,方法是使 JavaFX 应用程序成为非模块化的,并在您使用的基本 JDK 中提供 JavaFX 模块或通过命令行开关。 欲了解更多信息,请参阅答案:
删除
module-info.java
使项目成为非模块化项目。仅将 JavaFX 模块放置在模块路径上,并通过 VM 参数 --module-path
和 --add-modules
添加它们。 有关设置的更多信息,请参阅 openjfx.io 的入门文档。
有关非模块化应用程序的分发,请参阅:
补充:这里有两个现成的模板,包含 JavaFX、Spring Boot 和 Maven/Gradle。
我将感谢 GitHub 上的明星支持它的免费开源,从而帮助您解决问题。 <3
https://github.com/davidweber411/javafx-JavaFxSpringBootGradleApp
https://github.com/davidweber411/javafx-JavaFxSpringBootMavenApp