[SPRING] JavaFX 및 Spring - Bean은 자동 연결을 지원하지 않습니다.
SPRINGJavaFX 및 Spring - Bean은 자동 연결을 지원하지 않습니다.
JavaFX와 Spring의 결합에 문제가 있습니다. 나는 잘 작동하는 간단한 JavaFX 응용 프로그램이 있습니다. 이제는 스프링을 추가하려고합니다. 나는 봄 튜토리얼로 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
Startup.java는 main이있는 파일입니다.
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();
}
}
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));
}
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...
}
내 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;
}
}
My Spring 애플리케이션 구성 :
@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();
}
}
내 응용 프로그램에서 바인드 된 컨트롤러 ImageViewer.fxml있다 :
<AnchorPane fx:controller="mycompany.imageviewer.controller.ImageViewerController" xmlns="http://javafx.com/javafx/8.0.51" xmlns:fx="http://javafx.com/fxml/1" >
내가 프로그램을 실행할 때 로그를 얻는다.
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
어떤 표시, 내 컨트롤러가 두 번 초기화되고 dataProvider 제대로 바인딩되지 않습니다. 내가 혼란스럽게 만들었던 것은 내가 우발적으로 잘못된 패키지로 이런 식으로 ComponentScan에 잘못된 basePackages를 작성했을 때였 다.
@ComponentScan(basePackages = {"mycompany.imageviewer.dataprovider.controller", "mycompany.imageviewer.dataprovider.dataprovider.impl" })
Beans는 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
basePackages = "com.capgemini.starterkit.imageviewer"를 실행하면 효과가 첫 번째 경우와 같습니다. 나는 봄에 익숙하지 않고 아마도 몇 가지 간단한 실수를했지만 아마도 그것을 찾을 수 없기 때문에 누군가가 내가 봄을 구성하도록 도와 줄 수 있다면 좋을 것이다. :-)
해결법
-
==============================
1.호출중인 FXMLLoader.load (URL, ResourceBundle) 메서드는 정적 메서드입니다. 따라서 실제로 인스턴스화 한 FXMLLoader 인스턴스에는 아무런주의를 기울이지 않아 결과적으로 Spring bean factory를 참조하는 controllerFactory를 무시합니다.
호출중인 FXMLLoader.load (URL, ResourceBundle) 메서드는 정적 메서드입니다. 따라서 실제로 인스턴스화 한 FXMLLoader 인스턴스에는 아무런주의를 기울이지 않아 결과적으로 Spring bean factory를 참조하는 controllerFactory를 무시합니다.
다음과 같이 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; } }
이것은 컨트롤러 팩토리를 사용할 인스턴스 메소드 loader.load ()를 사용합니다. 즉, 컨트롤러를 인스턴스화하기 위해 Spring을 사용합니다.
컨트롤러가 두 번로드되는 이유는 기본적으로 Bean 팩토리가 컨트롤러 싱글 톤 범위를 제공하고 열심히 만들어 주므로 빈 팩토리 (applicationContext)를 생성하자마자 컨트롤러를 생성합니다. 해당 컨트롤러는 dataProvider를 초기화합니다 (단, 생성자가 완료된 후에 만). 그런 다음 정적 FXMLLoader.load (...) 메서드를 호출하면 일반적인 메커니즘 (즉, 인수가없는 생성자를 호출하여)에 의해 두 번째 컨트롤러가 만들어집니다. 이 인스턴스는 언제라도 dataProvider를 초기화하지 않습니다.
제쳐두고, 아마도 컨트롤러가 싱글 톤이되는 것을 원하지 않을 것입니다. FXML 파일을 두 번로드하면 Parent의 두 인스턴스를 얻으려면 각각의 인스턴스에 고유 한 컨트롤러가 있어야합니다. 그렇지 않으면 이상한 동작이 발생합니다. 컨트롤러를 프로토 타입으로 만드는 것을 추천한다. 이는 단일 인스턴스를 재사용하는 대신 빈 팩토리가 요청 될 때마다 새 인스턴스를 생성한다는 것을 의미한다. 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(); } }
from https://stackoverflow.com/questions/32424878/javafx-and-spring-beans-doesnt-autowire by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] Date 만 사용하는 Spring 데이터 쿼리 (0) | 2019.04.13 |
---|---|
[SPRING] 스프링 부트 WebClient를 사용하여 페이지 매김 된 API 응답을 수집하는 방법? (0) | 2019.04.13 |
[SPRING] SD MongoDB 다형성 하위 문서 (0) | 2019.04.13 |
[SPRING] messageSource를 사용하여 봄 메시지 코드를 해결할 수 없습니다. (0) | 2019.04.13 |
[SPRING] Spring 애플리케이션 컨텍스트 파일에리스트 정의하기 (0) | 2019.04.13 |