【问题标题】:Spring data jpa with java FX带有 java FX 的 Spring 数据 jpa
【发布时间】:2020-07-31 02:52:45
【问题描述】:

我将 Spring JPA 与 OpenJFX 一起使用。就是这个项目JavaFX-weaver,简单的在pom里面加上spring-boot-start-data-jpa。

但是我的 Spring JPA 开始时间是 15-20 秒,并且 UI 在 spring 初始化之前不会显示。当用户启动应用程序时,每次都需要很长时间!

作为一种解决方法,我尝试创建一个不带 Spring 的简单 java fx 应用程序(使用此演示 here),然后在 main 方法中从 spring 按钮上的 main 方法开始(参见下面的示例)。这将开始 spring,但依赖项和属性没有被加载。

你知道练习这种情况的好方法吗?欢迎任何帮助。

谢谢

AppBootstrap (Java + OpenJFX)

public class AppBootstrap extends Application {

    @Override
    public void start(Stage primaryStage) {

        Button btn = new Button();

        // start spring jpa main method
        btn.setOnAction(event -> App.main(new String[]{""})); 

        StackPane root = new StackPane();
        root.getChildren().add(btn);

        primaryStage.setScene(new Scene(root, 300, 250));
        primaryStage.show();
    }

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

应用程序(Spring JPA + javafx-weaver)

@SpringBootApplication
public class App {
    public static void main(String[] args) {
        Application.launch(SpringbootJavaFxApplication.class, args);
    }
}

【问题讨论】:

    标签: spring spring-boot javafx-8 openjfx spring-boot-jpa


    【解决方案1】:

    启动 JPA 驱动的应用程序会增加 ApplicationContext 的加载时间。虽然您可以通过不检查或创建数据库方案来使事情变得更快,例如通过设置hibernate.hbm2ddl.auto=none,这不是最好的选择。

    根据设计,主阶段在 ApplicationContext 加载之后显示,因为它应该能够被依赖注入。

    我推荐的最佳做法是在加载 ApplicationContext 时使用闪屏。这有点棘手,因为您有单独的线程,但大致看起来像这样:

    创建启动窗口

    public class Splash {
    
        private static final int SPLASH_WIDTH = 200;
        private static final int SPLASH_HEIGHT = 200;
    
        private final Parent parent;
        private final Stage stage; 
    
        public Splash() {
            this.stage = new Stage();
            stage.setWidth(SPLASH_WIDTH);
            stage.setHeight(SPLASH_HEIGHT);
            Label progressText = new Label("Application loading ...");
            VBox splashLayout = new VBox();
            splashLayout.setAlignment(Pos.CENTER);
            splashLayout.getChildren().addAll(progressText);
            progressText.setAlignment(Pos.CENTER);
            splashLayout.setStyle(
                    "-fx-padding: 5; " +
                            "-fx-background-color: white; " +
                            "-fx-border-width:5; " +
                            "-fx-border-color: white;"
            );
            splashLayout.setEffect(new DropShadow());
            this.parent = splashLayout;
        }
    
        public void show() {
            Scene splashScene = new Scene(parent);
            stage.initStyle(StageStyle.UNDECORATED);
            final Rectangle2D bounds = Screen.getPrimary().getBounds();
            stage.setScene(splashScene);
            stage.setX(bounds.getMinX() + bounds.getWidth() / 2 - SPLASH_WIDTH / 2.0);
            stage.setY(bounds.getMinY() + bounds.getHeight() / 2 - SPLASH_HEIGHT / 2.0);
            stage.show();
        }
    
        public void hide() {
            stage.toFront();
            FadeTransition fadeSplash = new FadeTransition(Duration.seconds(0.3), parent);
            fadeSplash.setFromValue(1.0);
            fadeSplash.setToValue(0.0);
            fadeSplash.setOnFinished(actionEvent -> stage.hide());
            fadeSplash.play();
        }
    }
    
    

    初始化应用程序

    public class SpringbootJavaFxApplication extends Application {
    
        private ConfigurableApplicationContext context;
    
        class ApplicationContextLoader extends Task<Void> {
    
            private final Stage primaryStage;
    
            ApplicationContextLoader(Stage primaryStage) {
                this.primaryStage = primaryStage;
            }
    
            @Override
            protected Void call() {
                ApplicationContextInitializer<GenericApplicationContext> initializer =
                        context -> {
                            context.registerBean(Application.class, () -> SpringbootJavaFxApplication.this);
                            context.registerBean(Stage.class, () -> primaryStage);
                            context.registerBean(Parameters.class,
                                    SpringbootJavaFxApplication.this::getParameters); // for demonstration, not really needed
                        };
                SpringbootJavaFxApplication.this.context = new SpringApplicationBuilder()
                        .sources(JavaFxSpringbootDemo.class)
                        .initializers(initializer)
                        .run(getParameters().getRaw().toArray(new String[0]));
    
                return null;
            }
        }
    
        @Override
        public void start(Stage primaryStage) {
            var splash = new Splash();
            splash.show();
            final ApplicationContextLoader applicationContextLoader = new ApplicationContextLoader(primaryStage);
            applicationContextLoader.stateProperty().addListener((observableValue, oldState, newState) -> {
                if (newState == Worker.State.SUCCEEDED) {
                    context.publishEvent(new StageReadyEvent(primaryStage));
                    splash.hide();
                }
            });
            new Thread(applicationContextLoader).start();
        }
    
        @Override
        public void stop() {
            this.context.close();
            Platform.exit();
        }
    }
    

    【讨论】:

    • 非常感谢。这是一个很好的解决方案,正是搜索的内容.. 很棒
    猜你喜欢
    • 1970-01-01
    • 2021-05-26
    • 1970-01-01
    • 2017-02-20
    • 2014-09-02
    • 2018-01-08
    • 2015-06-20
    • 1970-01-01
    • 2015-07-30
    相关资源
    最近更新 更多