我有一个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与哈希码相同,这意味着它是相同的实例。因此,它没有创建一个新的。
也许我错误地加载了我的FXML,或者只是Spring-Boot控制器工厂在这种情况下工作很奇怪。有什么建议吗?
答案 0 :(得分: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配置为具有“原型”范围。使用“prototype”范围,每次都会创建一个新实例。
定义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>