FXML Loader 不创建新实例
FXML Loader does not create new instance
我有一个 JavaFX + Spring 引导应用程序。当我尝试用它的控制器加载新的 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- 引导控制器工厂在这种情况下工作异常。有什么建议吗?
行
loader.setControllerFactory(context::getBean);
指示 FXMLLoader
从 spring 应用程序上下文中获取控制器:在内部,FXMLLoader
现在将执行类似
的操作
Class controllerClass = Class.forName(classNameFromFXMLFile);
Object controller = context.getBean(controllerClass);
getBean
的行为取决于您如何为该 class 配置 bean,但默认情况下它将具有 "singleton" 范围。这意味着它会创建一个 class 的实例,并且 return 每次使用映射到该 bean 的参数调用 getBean(...)
时都会创建相同的实例(例如 class豆)。
每次加载 FXML 文件时,您几乎肯定需要控制器的新实例 class,因此您应该将 bean 配置为具有 "prototype" 作用域。使用 "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>
我有一个 JavaFX + Spring 引导应用程序。当我尝试用它的控制器加载新的 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- 引导控制器工厂在这种情况下工作异常。有什么建议吗?
行
loader.setControllerFactory(context::getBean);
指示 FXMLLoader
从 spring 应用程序上下文中获取控制器:在内部,FXMLLoader
现在将执行类似
Class controllerClass = Class.forName(classNameFromFXMLFile);
Object controller = context.getBean(controllerClass);
getBean
的行为取决于您如何为该 class 配置 bean,但默认情况下它将具有 "singleton" 范围。这意味着它会创建一个 class 的实例,并且 return 每次使用映射到该 bean 的参数调用 getBean(...)
时都会创建相同的实例(例如 class豆)。
每次加载 FXML 文件时,您几乎肯定需要控制器的新实例 class,因此您应该将 bean 配置为具有 "prototype" 作用域。使用 "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>