JavaFX 应用程序中的 Spring 应用程序上下文

Posted

技术标签:

【中文标题】JavaFX 应用程序中的 Spring 应用程序上下文【英文标题】:Spring Application Context in JavaFX Application 【发布时间】:2016-09-07 19:45:24 【问题描述】:

我有兴趣在 JavaFX 应用程序中使用 ApplicationContext。我问自己是否有更聪明的方法来处理 ApplicationContext 作为 Application 子类本身的属性。

@Configuration
@ComponentScan("...")
public class Gui extends Application 

   private AnnotationConfigApplicationContext context;

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

   /* (non-Javadoc)
    * @see javafx.application.Application#start(javafx.stage.Stage)
    */

    @Override
    public void start(Stage stage) throws Exception        
      context = new AnnotationConfigApplicationContext(Gui.class);
      //...         
           

我打算将ApplicationContextGui.class 分开,并使用@Autowired 注释在Gui.class 中注入弹簧组件。

【问题讨论】:

【参考方案1】:

首先,将应用程序配置与Application 子类分开。 JavaFX 将为您创建 Application 子类的实例,并且该类应该只有一个实例。 Spring 将创建任何配置类的实例,因此,即使您无权访问它们,最终也会得到 Application 类的多个实例,这不是预期用途。

至于您正在寻找的分离,我认为您想要的是将 ApplicationContext 的创建和交互与构建和配置 UI 的工作分开,并使其与业务层交互应用程序等。但是,我认为您正在从应有的方式向后看。 Application 类,特别是它的start() 方法,是JavaFX 应用程序的入口点。 FX 框架在启动时会做一些内务处理(启动 FX 工具包等),创建该类的实例,并调用 start 方法。由于这是您对应用程序进行基本组装的地方,因此创建ApplicationContext 并从中获取一两个bean 是自然而正确的地方。如果您想将此与创建和配置 UI 分开,则应该将 UI 的创建和配置移到其他地方。 Application 类的唯一职责应该是启动应用程序:这样根本就没有状态可以注入到该类中。

使用这种方法,一个最小的 Spring 驱动的 FX 应用程序可能看起来像:

AppConfig.java:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;

@Configuration
public class AppConfig 

    @Bean
    public Service service() 
        return new Service();
    

    @Bean
    @Scope("prototype")
    public Gui gui() 
        return new Gui();
    

Service.java:

public class Service 

    public String confirmationMessage() 
        return "You have been confirmed";
    

Gui.java(注意这不是 Application 的子类,但它几乎完成了所有的 GUI 工作):

import javax.annotation.PostConstruct;
import javax.inject.Inject;

import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Parent;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;

public class Gui 

    @Inject
    private Service service ;

    private VBox view ;
    private Label label ;

    public Gui() 
        Button button = new Button("Press for confirmation");
        label = new Label();
        label.setVisible(false);
        button.setOnAction(e -> label.setVisible(true));

        view = new VBox(5, label, button);
        view.setPadding(new Insets(20));
        view.setAlignment(Pos.CENTER);
    

    @PostConstruct
    private void init() 
        label.setText(service.confirmationMessage());
    

    public Parent getView() 
        return view ;
    

最后,Application 类 Main.java。请注意,这实际上并没有做任何 GUI 工作:它只是管理应用程序生命周期:创建 ApplicationContext,从中获取代表主视图的 bean,并将其显示在初级阶段。所有实际的 GUI 工作都委托给 MainView 类,其实例由 Spring 管理。

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;

import javafx.application.Application;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Main extends Application 

    private AbstractApplicationContext context ;

    @Override
    public void start(Stage primaryStage) 
        context = new AnnotationConfigApplicationContext(AppConfig.class);
        Parent mainView = context.getBean(Gui.class).getView();
        primaryStage.setScene( new Scene(mainView) );
        primaryStage.show();
    

    @Override
    public void stop() 
        context.close();
    

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

您可以扩展此方法,使其对表示层使用完整的 MVC/MVP 设计,如果需要,可以使用 FXML,等等。

【讨论】:

谢谢!!!我认为这是分离类职责的好方法。

以上是关于JavaFX 应用程序中的 Spring 应用程序上下文的主要内容,如果未能解决你的问题,请参考以下文章

JPackaged JavaFX + Spring boot 不启动

我应该怎么做才能获得我的 javafx spring boot 桌面应用程序的 OAuth2 访问令牌?

JavaFX UI 在事件侦听器中的 JavaFX 应用程序线程中冻结,但可与 Platform.runLater 一起使用

如何将 Spring 与 JavaFX 一起使用?

javafx已经没多少用了

JavaFX 2.1 中的应用程序范围的菜单栏?