sus*_*usz 4 java spring javafx
我在组合JavaFX和Spring方面遇到了问题.我有简单的JavaFX应用程序,它工作正常.现在我想尝试添加一些Spring.我在Spring Tutorial中使用了JavaFX 2.我的代码:
src/main
|
|_java/mycompany/imageviewer
| |
| |_Startup.java
| |_controller/ImageViewController.java
| |_dataprovider
| |impl/DataProviderImpl.java
| |_config
| |_SpringFxmlLoader.java
| |_SpringApplicationConfig.java
|_resources/mycompany/view/ImageViewer.fxml
Run Code Online (Sandbox Code Playgroud)
Startup.java
是主文件:
public class Startup extends Application {
private static final SpringFxmlLoader loader = new SpringFxmlLoader();
public static void main(String[] args) {
Application.launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
...
Parent root = (Parent) loader.load("/mycompany/imageviewer/view/ImageViewer.fxml","mycompany/imageviewer/bundle/bundle");
Scene scene = new Scene(root);
...css etc...
primaryStage.setScene(scene);
primaryStage.show();
}
}
Run Code Online (Sandbox Code Playgroud)
ImageviewerController.java
:
@Controller
public class ImageViewerController {
private static final Logger LOG = Logger.getLogger(ImageViewerController.class);
@FXML
...
@Autowired
private DataProvider dataProvider;
public ImageViewerController() {
LOG.debug("Controller initialized. DataProvider is null: "+(dataProvider==null));
}
Run Code Online (Sandbox Code Playgroud)
DataProviderImpl.java
:
@Service("dataProvider")
public class DataProviderImpl implements DataProvider {
private static final Logger LOG = Logger.getLogger(DataProviderImpl.class);
public DataProviderImpl() {
LOG.debug("DataProviderImpl initialized.");
}
...methods...
}
Run Code Online (Sandbox Code Playgroud)
我的SpringFxmlLoader在教程中看起来与此类似:
public class SpringFxmlLoader {
private static final ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringApplicationConfig.class);
public Object load(String url, String resources) {
FXMLLoader loader = new FXMLLoader();
loader.setControllerFactory(clazz -> applicationContext.getBean(clazz));
try {
return loader.load(getClass().getResource(url), ResourceBundle.getBundle(resources));
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
Run Code Online (Sandbox Code Playgroud)
我的SpringApplicationConfig:
@Configuration
@ComponentScan(basePackages = {"mycompany.imageviewer.controller", "mycompany.imageviewer.dataprovider.impl" })
public class SpringApplicationConfig {
private static final Logger LOG = Logger.getLogger(SpringApplicationConfig.class);
@Bean
public DataProvider dataProvider() {
LOG.debug("Initializing dataProvider via SpringApplicationConfig");
return new DataProviderImpl();
}
@Bean
public ImageViewerController imageViewerController() {
LOG.debug("Initializing ImageViewerController via SpringApplicationConfig");
return new ImageViewerController();
}
}
Run Code Online (Sandbox Code Playgroud)
在我的应用程序中,我有ImageViewer.fxml
绑定控制器:
<AnchorPane fx:controller="mycompany.imageviewer.controller.ImageViewerController" xmlns="http://javafx.com/javafx/8.0.51" xmlns:fx="http://javafx.com/fxml/1" >
Run Code Online (Sandbox Code Playgroud)
当我运行程序时,我得到日志:
DEBUG [main] mycompany.imageviewer.controller.ImageViewerController:74 - Controller initialized. DataProviderImpl is null: true
DEBUG [main] mycompany.imageviewer.dataprovider.impl.DataProviderImpl:22 - DataProviderImpl initialized.
DEBUG [JavaFX Application Thread] mycompany.imageviewer.controller.ImageViewerController:74 - Controller initialized. DataProviderImpl is null: true
Run Code Online (Sandbox Code Playgroud)
这表明,我的控制器初始化了两次,而且dataProvider
没有正确绑定.是什么让我困惑,是我不期而遇写错basePackages
以ComponentScan
这种方式与错的包:
@ComponentScan(basePackages = {"mycompany.imageviewer.dataprovider.controller", "mycompany.imageviewer.dataprovider.dataprovider.impl" })
Run Code Online (Sandbox Code Playgroud)
Bean在SpringApplicationConfig.java
运行中初始化方法,我从中获取日志:
2015-09-06 16:52:29,420 DEBUG [main] com.capgemini.starterkit.imageviewer.config.SpringApplicationConfig:19 - Initializing dataProvider via SpringApplicationConfig
2015-09-06 16:52:29,431 DEBUG [main] com.capgemini.starterkit.imageviewer.dataprovider.impl.DataProviderImpl:22 - DataProviderImpl initialized.
DEBUG [main] mycompany.imageviewer.config.SpringApplicationConfig:25 - Initializing ImageViewerController via SpringApplicationConfig
DEBUG [main] mycompany.imageviewer.controller.ImageViewerController:74 - Controller initialized. DataProviderImpl is null: true
DEBUG [JavaFX Application Thread] mycompany.imageviewer.controller.ImageViewerController:74 - Controller initialized. DataProviderImpl is null: true
Run Code Online (Sandbox Code Playgroud)
当我运行basePackages = "com.capgemini.starterkit.imageviewer"
效果与第一种情况相同时.我是春天的新手,可能我犯了一些简单的错误,但是我找不到它们,所以如果有人能帮我配置那个很棒的弹簧.:-)
在FXMLLoader.load(URL, ResourceBundle)
您所呼叫的方法是一种static
方法-因此它实际上不关注了FXMLLoader
你化实例,以及因此忽略了controllerFactory
它引用您的Spring bean工厂.
重写你的SpringFXMLLoader
课程如下:
public class SpringFxmlLoader {
private static final ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringApplicationConfig.class);
public Object load(String url, String resources) {
FXMLLoader loader = new FXMLLoader();
loader.setControllerFactory(clazz -> applicationContext.getBean(clazz));
loader.setLocation(getClass().getResource(url));
loader.setResources(ResourceBundle.getBundle(resources));
try {
return loader.load();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
Run Code Online (Sandbox Code Playgroud)
这使用将使用您的控制器工厂的实例方法loader.load()
:即它将使用Spring来实例化控制器.
您看到控制器加载两次的原因是,默认情况下,bean工厂为控制器提供单例作用域并使其热切创建,因此只要您创建bean工厂(applicationContext
),它就会创建一个控制器.该控制器将dataProvider
初始化(但只有在构造函数完成后才会进行初始化).然后,对静态FXMLLoader.load(...)
方法的调用通过常规机制创建第二个控制器(即通过调用其无参数构造函数).该实例不会dataProvider
在任何时候进行初始化.
顺便说一句,你可能不希望控制器成为单身人士.如果你要加载你的FXML文件两次,得到两个实例Parent
,你可能需要每个实例都有自己的控制器,否则会出现奇怪的行为.我建议将控制器作为原型(这意味着bean工厂将在每次请求时创建一个新实例,而不是重用单个实例).您可以在config类中执行以下操作:
@Configuration
@ComponentScan(basePackages = {"mycompany.imageviewer.controller", "mycompany.imageviewer.dataprovider.impl" })
public class SpringApplicationConfig {
private static final Logger LOG = Logger.getLogger(SpringApplicationConfig.class);
@Bean
public DataProvider dataProvider() {
LOG.debug("Initializing dataProvider via SpringApplicationConfig");
return new DataProviderImpl();
}
@Bean
@Scope("prototype")
public ImageViewerController imageViewerController() {
LOG.debug("Initializing ImageViewerController via SpringApplicationConfig");
return new ImageViewerController();
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
3685 次 |
最近记录: |