Spring data jpa с java FX - PullRequest
       74

Spring data jpa с java FX

2 голосов
/ 17 апреля 2020

Я использую Spring JPA с OpenJFX. Именно этот проект JavaFX-weaver , просто добавляющий spring-boot-start-data-jpa внутри pom.

Однако мое время запуска Spring JPA составляет 15-20 с, и пользовательский интерфейс не будет отображаться пока весна не будет инициализирована. Когда пользователи запускают приложение, это занимает много времени, каждый раз!

В качестве обходного пути я попытался создать простое java fx-приложение без Spring (используя эту демонстрацию здесь ), а затем запустив там основной метод main с помощью spring поверх кнопки (см. пример ниже). Это начнется весной, но зависимости и свойства не загружаются.

Знаете ли вы хороший способ попрактиковаться в этом случае? Любая помощь приветствуется.

Спасибо

Приложение Bootstrap (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);
    }
}

1 Ответ

1 голос
/ 23 апреля 2020

Запуск приложения с поддержкой JPA увеличивает время загрузки ApplicationContext. Хотя вы можете ускорить процесс, не проверяя и не создавая схему базы данных, например, установив hibernate.hbm2ddl.auto=none, это не лучший вариант.

По своей сути основной этап отображается после ApplicationContext загружен, поскольку он должен быть способен вводить зависимости.

Лучшая практика, которую я рекомендую, - использовать экран spla sh при загрузке ApplicationContext. Это немного сложно, так как у вас есть отдельные потоки, но примерно это выглядит так:

Создать окно spla sh

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();
    }
}

Initialize Приложение

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();
    }
}
...