javaFX 应用程序中的 Spring Boot(模块化问题)

问题描述 投票:0回答:2

我正在尝试在 javaFX 应用程序中使用 SpringBoot。我使用 javafx-weaver-spring-boot-starter,它与 java 配合得很好 < 9, but there are some problems with java 9+ (modularity). My project structure: enter image description here

应用程序启动代码:

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 javafx
2个回答
1
投票

Spring 5 与 JavaFX 平台模块系统不友好

Spring 不会真正为模块构建,直到 Spring 6/Springboot 3 发布。

Spring Framework 6 确实有望为所有核心框架模块引入模块信息描述符,对核心 Java 模块所需的依赖性最小,从而使 JDK 的 jlink 工具能够为 Spring 设置构建自定义运行时映像。可选的第三方库和某些配置策略可能会受到限制,因此目前还不清楚这种显式模块的使用在 Spring 用户中会变得多么流行。

对于基于 Spring 5 的应用程序,该框架不容易与 Java 平台模块系统兼容。

所以我不建议尝试构建依赖于 Spring 的模块化 JavaFX 应用程序,直到:

  1. Spring 6/SpringBoot 3 发布,

    并且

  2. 您使用的依赖库也可以轻松兼容Java模块系统。

    • 例如,当所有依赖项都定义了
      module-info.java
      时。

如何使您的项目非模块化

但是,您今天仍然可以构建依赖于 Spring 5 的 JavaFX 17 应用程序,方法是使 JavaFX 应用程序成为非模块化的,并在您使用的基本 JDK 中提供 JavaFX 模块或通过命令行开关。 欲了解更多信息,请参阅答案:

删除

module-info.java
使项目成为非模块化项目。仅将 JavaFX 模块放置在模块路径上,并通过 VM 参数
--module-path
--add-modules
添加它们。 有关设置的更多信息,请参阅 openjfx.io 的入门文档

有关非模块化应用程序的分发,请参阅:


0
投票

补充:这里有两个现成的模板,包含 JavaFX、Spring Boot 和 Maven/Gradle。

我将感谢 GitHub 上的明星支持它的免费开源,从而帮助您解决问题。 <3

https://github.com/davidweber411/javafx-JavaFxSpringBootGradleApp

https://github.com/davidweber411/javafx-JavaFxSpringBootMavenApp

© www.soinside.com 2019 - 2024. All rights reserved.