JavaFX приложение падает при попытке сделать контроллер бином
Из ответов на вопрос Как обеспечить доступ к бинам для классов, не являющихся точкой входа в приложение (и бинами)? я так и не узнал, как же обеспечить доступ к бинам для тех классов, которые сами бинами не являются. Пришлось делать делать JavaFX-контроллер бином:
@Component
public class PersonOverviewController {
private final PeopleGateway peopleGateway;
// ...
@Autowired
public PersonOverviewController(PeopleGateway peopleGateway) {
this.peopleGateway = peopleGateway;
}
@FXML
private void initialize() {
System.out.println("===");
System.out.println(peopleGateway);
// Если инъекция произведена успешно, то это не должен быть null
}
// ...
}
Привело это к тому, что приложение стало падать по непонятной мне причине. Из сообщений об ошибке ясно, что JavaFX то ли потерял контроллер, то ли не может им манипулировать:
Caused by: java.lang.InstantiationException: dev.example.Controllers.PersonOverviewController
at java.base/java.lang.Class.newInstance(Class.java:598)
at javafx.fxml.FXMLLoader$ValueElement.processAttribute(FXMLLoader.java:936)
... 18 more
Caused by: java.lang.NoSuchMethodException: dev.example.Controllers.PersonOverviewController.<init>()
at java.base/java.lang.Class.getConstructor0(Class.java:3427)
at java.base/java.lang.Class.newInstance(Class.java:585)
... 19 more
Конфигурация приложения:
@Configuration
public class ApplicationContextConfig {
@Bean
public FilesManager filesManager() {
return new RegularFilesManager();
}
@Bean
public PeopleGateway peopleGateway() { return new PeopleGatewayWithMockData(); }
@Bean
public PersonOverviewController personOverviewController() {
return new PersonOverviewController(this.peopleGateway());
}
}
Полный код приложения доступен на Bit-bucket-репозитории. Также прилагаю ссылку на код приложения в рабочем состоянии.
Ответы (1 шт):
FXMLLoader вроде как не умеет в constructor Injection, и контроллер создать не сможет, да и в данном случае не должен. Для использования "внешнего" DI предусмотрен специальный механизм c ControllerFactory:
FXMLLoader loader = new FXMLLoader();
loader.setControllerFactory(applicationContext::getBean);
ControllerFactory имеет тип Callback<Class<?>, Object>, в данном случае ссылка на метод, applicationContext::getBean где applicationContext - это спринговый ApplicationContext.