将Spring与JavaFX服务类集成会导致服务失败
背景 我正在开发一个JavaFX应用程序,根据我的偏好自动管理、编辑和移动文件。最终,应用程序将有相当多的任务需要一些繁重的处理。我想有一个单一的任务栏显示在屏幕的底部,可以利用和显示每个任务时,它正在运行,否则隐藏 由于任务可能非常耗时,我希望在进度条旁边显示一个cancel task图标,该图标也可以是通用的,单击时可以取消当前正在执行的任务将Spring与JavaFX服务类集成会导致服务失败,java,spring,multithreading,spring-boot,javafx,Java,Spring,Multithreading,Spring Boot,Javafx,背景 我正在开发一个JavaFX应用程序,根据我的偏好自动管理、编辑和移动文件。最终,应用程序将有相当多的任务需要一些繁重的处理。我想有一个单一的任务栏显示在屏幕的底部,可以利用和显示每个任务时,它正在运行,否则隐藏 由于任务可能非常耗时,我希望在进度条旁边显示一个cancel task图标,该图标也可以是通用的,单击时可以取消当前正在执行的任务 我的思维过程 为了实现这一点,我尽我所能提出的解决方案是为我的应用程序将拥有的每个任务创建一个唯一的类扩展任务,这个类将是一个普通(非Springb
我的思维过程 为了实现这一点,我尽我所能提出的解决方案是为我的应用程序将拥有的每个任务创建一个唯一的类扩展任务,这个类将是一个普通(非Springbean)类 然后还为这些任务中的每一个创建一个唯一的类扩展服务,然后在服务类中,重写的createTask()方法将返回相应任务的新实例。然而,这个服务类将是一个Springbean,因此可以自动连接到任何需要使用服务来运行任务的控制器类中
问题 当我单击最终启动服务的按钮时,服务最终会失败并进入失败状态。当我查看调试器时,似乎异常是由于文件浏览器控制器为null而导致的null指针异常而发生的。但是,当文件浏览器控制器由service createTask()方法实例化时,它应该自动连接到任务类中 我不能100%确定这是问题的原因,因为调试服务被证明有点困难,但似乎是因为这是在服务设置为“失败”之前设置为任务值的异常
代码 控制器类(启动服务)
我尝试过的解决方案 最初,我还想将任务声明为原型Springbean,然后将它们作为属性自动关联到服务中,然后在createTask()方法中返回自动关联值。这个解决方案在我第一次单击按钮时可以工作,但第二次它会抛出一个异常,因为Spring只会在第一次通过时创建task属性的一个新实例,一旦服务被重置并且任务被设置为null,它就再也不会被创建了。请参见下面的代码片段 带有自动连线任务的服务
@组件
公共类GetSelectedFilesCountService扩展服务{
@自动连线
私有GetSelectedFilesCountTask GetSelectedFilesCountTask;
@凌驾
受保护的任务createTask(){
返回getSelectedFilesCountTask;
}
}
在这之后,我决定也许我仍然可以通过为任务创建一个bean工厂,然后调用bean工厂的createBean()方法来返回任务的一个新实例来完成上述任务,但最终这不起作用,我觉得我可以通过基本上使用服务作为工厂来完成同样的事情,用一半的代码创建新实例
更新 我仍然想知道上面代码的原始问题是什么(返回任务子类的新实例),但现在我找到了一个解决方案。。。。或者通过创建并返回匿名任务实例来解决问题。我想这是可以接受的,因为我不必重复代码,因为服务可以被多次使用,但我仍然希望代码在自己的类中。这很奇怪,因为这与我在Task子类中一直失败的代码完全相同,但我猜。请参阅下面的代码片段,以防对其他人有所帮助
@Component
public class GetSelectedFilesCountService extends Service<Integer> {
@Autowired
private FileBrowserController fileBrowserController;
private Integer leafCount;
@Override
protected Task<Integer> createTask() {
return new Task<Integer>() {
@Override
protected Integer call() {
leafCount = 0;
getSelectedItemsLeafCount(fileBrowserController.getFileBrowser().getSelectionModel().getSelectedItems());
return leafCount;
}
/*****************************************************************
*Recursively counts the leaves within a single or group of Files
*****************************************************************/
private void getSelectedItemsLeafCount(List<TreeItem<File>> files) {
for(TreeItem<File> f : files) {
if(f.isLeaf()) {
leafCount++;
}else {
getSelectedItemsLeafCount(f.getChildren());
}
}
}
};
}
}
@Component
public class GetSelectedFilesCountService extends Service<Integer> {
@Autowired
private FileBrowserController fileBrowserController;
private Integer leafCount;
@Override
protected Task<Integer> createTask() {
return new Task<Integer>() {
@Override
protected Integer call() {
leafCount = 0;
getSelectedItemsLeafCount(fileBrowserController.getFileBrowser().getSelectionModel().getSelectedItems());
return leafCount;
}
/*****************************************************************
*Recursively counts the leaves within a single or group of Files
*****************************************************************/
private void getSelectedItemsLeafCount(List<TreeItem<File>> files) {
for(TreeItem<File> f : files) {
if(f.isLeaf()) {
leafCount++;
}else {
getSelectedItemsLeafCount(f.getChildren());
}
}
}
};
}
}
@组件
公共类GetSelectedFilesCountService扩展服务{
@自动连线
私有文件浏览器控制器文件浏览器控制器;
私有整数叶数;
@凌驾
受保护的任务createTask(){
返回新任务(){
@凌驾
受保护的整数调用(){
叶数=0;
getSelectedItemsLeafCount(fileBrowserController.getFileBrowser().getSelectionModel().getSelectedItems());
返回叶数;
}
/*****************************************************************
*递归计算单个或一组文件中的叶数
*****************************************************************/
私有void getSelectedItemsLeafCount(列表文件){
用于(TreeItem f:文件){
if(f.isLeaf()){
叶数++;
}否则{
getSelectedItemsLeafCount(f.getChildren());
}
}
}
};
}
}
这不是一个完整的解决方案,但一个不错的解决办法是在服务的createTask方法中使用并返回匿名任务。出于某种原因,当我试图返回一个定义的Task子类的新实例,而Springbean没有被实例化时,会出现一个问题,如果您知道这是为什么,请发表评论
解决方案
@组件
公共类GetSelectedFilesCountService扩展服务{
@自动连线
私有文件浏览器控制器文件浏览器控制器;
私有整数叶数;
@凌驾
受保护的任务createTask(){
返回新任务(){
@凌驾
受保护的整数调用(){
叶数=0;
getSelectedItemsLeafCount(fileBrowserController.getFileBrowser()
@Component
public class GetSelectedFilesCountTask extends Task<Integer> {
@Autowired
private FileBrowserController fileBrowserController;
private Integer leafCount;
@Override
protected Integer call() {
leafCount = 0;
getSelectedItemsCount(fileBrowserController.getFileBrowser().getSelectionModel().getSelectedItems());
return leafCount;
}
/*****************************************************************
*Recursively counts the leaves within a single or group of Files
*****************************************************************/
private void getSelectedItemsCount(List<TreeItem<File>> files) {
for(TreeItem<File> f : files) {
if(f.isLeaf()) {
leafCount++;
}else {
getSelectedItemsLeafCount(f.getChildren());
}
}
}
@Override
protected void cancelled() {
updateMessage("Operation Cancelled");
}
}
@Configuration
public class SpringAppConfig {
@Bean
public DataModel datamodel() {
return new DataModel();
}
@Bean
public GetSelectedFilesCountService getSelectedFilesCountService() {
return new GetSelectedFilesCountService();
}
}
@Component
public class GetSelectedFilesCountService extends Service<Integer> {
@Autowired
private GetSelectedFilesCountTask getSelectedFilesCountTask;
@Override
protected Task<Integer> createTask() {
return getSelectedFilesCountTask;
}
}
@Component
public class GetSelectedFilesCountService extends Service<Integer> {
@Autowired
private FileBrowserController fileBrowserController;
private Integer leafCount;
@Override
protected Task<Integer> createTask() {
return new Task<Integer>() {
@Override
protected Integer call() {
leafCount = 0;
getSelectedItemsLeafCount(fileBrowserController.getFileBrowser().getSelectionModel().getSelectedItems());
return leafCount;
}
/*****************************************************************
*Recursively counts the leaves within a single or group of Files
*****************************************************************/
private void getSelectedItemsLeafCount(List<TreeItem<File>> files) {
for(TreeItem<File> f : files) {
if(f.isLeaf()) {
leafCount++;
}else {
getSelectedItemsLeafCount(f.getChildren());
}
}
}
};
}
}
@Component
public class GetSelectedFilesCountService extends Service<Integer> {
@Autowired
private FileBrowserController fileBrowserController;
private Integer leafCount;
@Override
protected Task<Integer> createTask() {
return new Task<Integer>() {
@Override
protected Integer call() {
leafCount = 0;
getSelectedItemsLeafCount(fileBrowserController.getFileBrowser().getSelectionModel().getSelectedItems());
return leafCount;
}
/*****************************************************************
*Recursively counts the leaves within a single or group of Files
*****************************************************************/
private void getSelectedItemsLeafCount(List<TreeItem<File>> files) {
for(TreeItem<File> f : files) {
if(f.isLeaf()) {
leafCount++;
}else {
getSelectedItemsLeafCount(f.getChildren());
}
}
}
};
}
}