首页 文章

FXML Loader不会创建新实例

提问于
浏览
0

我有一个JavaFX Spring Boot应用程序 . 当我尝试使用其控制器加载新的FXML时,它工作正常,但是当我第二次或第三次加载它时,它给了我相同的实例并且不创建新实例 .

我的FXML加载程序如下:

public <T> T loadAndGetController(String fxmlPath) throws IOException {
    FXMLLoader loader = new FXMLLoader();
    loader.setControllerFactory(context::getBean); // Spring now FXML Controller Factory
    loader.setLocation(getClass().getResource(fxmlPath));
    loader.setResources(ResourceBundle.getBundle("language/lang",
            new Locale(languageController.getLanguage().getValue(), languageController.getLanguage().toString())));
    loader.load();
    return loader.getController();
}

加载新的FXML:

TabController tabController = (TabController) StageManager.loadAndGetController(FXMLViews.TAB.getFxmlFile());

当我尝试将其添加到我加载的控制器列表中时,ID与哈希码相同,这意味着它是相同的实例 . 因此它没有创造一个新的 .

enter image description here

也许我正在加载我的FXML错误或只是Spring-Boot控制器工厂在这种情况下工作很奇怪 . 有什么建议?

1 回答

  • 2

    这条线

    loader.setControllerFactory(context::getBean);
    

    指示 FXMLLoader 从spring应用程序上下文中获取控制器:在内部, FXMLLoader 现在将执行类似的操作

    Class controllerClass = Class.forName(classNameFromFXMLFile);
    Object controller = context.getBean(controllerClass);
    

    getBean 的行为取决于您为该类配置bean的方式,但默认情况下它将具有"singleton"范围 . 这意味着它将创建该类的一个实例,并且每次使用映射到该bean的参数(例如bean的类)调用 getBean(...) 时返回相同的实例 .

    每次加载FXML文件时,您几乎肯定需要一个新的控制器类实例,因此您应该将bean配置为具有“原型”范围 . 使用“原型”范围,每次都会创建一个新实例 .

    定义bean范围的机制取决于您如何配置应用程序上下文,但使用基于注释的配置,您可以执行类似的操作

    @Component
    @Scope(BeanDefinition.SCOPE_PROTOTYPE)
    public class FarTabController { /* ... */ }
    

    使用基于Java的配置,您可以这样做

    @Configuration
    public class ApplicationConfig {
    
        @Bean
        @Scope(BeanDefinition.SCOPE_PROTOTYPE)
        public FarTabController farTabController() {
            return new FarTabController() ;
        }
    
        // ...
    }
    

    如果你仍在使用旧的基于模式的(XML)配置,你会这样做(如果我没记错的话)

    <beans>
    
        <bean class="my.package.FarTabController" scope="prototype" />
    
        <!-- ... -->
    
    </beans>
    

相关问题