JavaFX 런타임은 Application 개체와 모든 컨트롤러 개체를 인스턴스화하려고하므로 이러한 개체에 종속성을 어떻게 주입합니까?종속성 삽입 및 JavaFX
개체가 Spring과 같은 DI 프레임 워크로 인스턴스화 된 경우 프레임 워크는 모든 종속성을 철회합니다. 개체를 수동으로 인스턴스화하는 경우에는 생성자 매개 변수를 통해 종속성을 제공합니다. 하지만 JavaFX 응용 프로그램에서 무엇을합니까?
감사합니다.
JavaFX 런타임은 Application 개체와 모든 컨트롤러 개체를 인스턴스화하려고하므로 이러한 개체에 종속성을 어떻게 주입합니까?종속성 삽입 및 JavaFX
개체가 Spring과 같은 DI 프레임 워크로 인스턴스화 된 경우 프레임 워크는 모든 종속성을 철회합니다. 개체를 수동으로 인스턴스화하는 경우에는 생성자 매개 변수를 통해 종속성을 제공합니다. 하지만 JavaFX 응용 프로그램에서 무엇을합니까?
감사합니다.
FXMLLoader
에 대해 controller factory을 지정할 수 있습니다. 컨트롤러 팩토리는 컨트롤러 클래스를 컨트롤러로 사용할 객체 (아마도 그 클래스의 인스턴스 일 수도 있지만 반드시 그런 것은 아님)에 매핑하는 함수입니다.
ApplicationContext context = ... ;
FXMLLoader loader = new FXMLLoader(getClass().getResource("path/to/fxml"));
loader.setControllerFactory(context::getBean);
Parent root = loader.load();
SomeController controller = loader.getController(); // if you need it...
// ...
그리고 지금 FXMLLoader
이 context.getBean(c);
를 호출하여 Class<?> c
에 대한 컨트롤러의 인스턴스를 생성합니다 :
그래서 당신은 봄 당신을위한 컨트롤러의 인스턴스를 만들려면,이처럼 간단 할 수있다. 당신이 DI 프레임 워크를 사용하지 않는 경우
@Configuration
public class AppConfig {
@Bean
public MyService service() {
return new MyServiceImpl();
}
@Bean
@Scope("prototype")
public SomeController someController() {
return new SomeController();
}
// ...
}
public class SomeController {
// injected by FXMLLoader:
@FXML
private TextField someTextField ;
// Injected by Spring:
@Inject
private MyService service ;
public void initialize() {
someTextField.setText(service.getSomeText());
}
// event handler:
@FXML
private void performAction(ActionEvent e) {
service.doAction(...);
}
}
과 함께, 당신은 "손으로"주사를 수행 할 :
그래서, 예를 들어, 당신은 구성을 가질 수있다 , 그렇게 할 수는 있지만 상당히 많은 것을 반영해야합니다. 체크 아웃 할 수 있습니다,
FXMLLoader loader = new FXMLLoader(getClass().getResource("path/to/fxml"));
MyService service = new MyServiceImpl();
loader.setControllerFactory((Class<?> type -> {
try {
// look for constructor taking MyService as a parameter
for (Constructor<?> c : type.getConstructors()) {
if (c.getParameterCount() == 1) {
if (c.getParameterTypes()[0]==MyService.class) {
return c.newInstance(service);
}
}
}
// didn't find appropriate constructor, just use default constructor:
return type.newInstance();
} catch (Exception exc) {
throw new RuntimeException(exc);
}
});
Parent root = loader.load();
// ...
을 한 후 바로
public class SomeController {
private final MyService service ;
public SomeController(MyService service) {
this.service = service ;
}
// injected by FXMLLoader:
@FXML
private TextField someTextField ;
public void initialize() {
someTextField.setText(service.getSomeText());
}
// event handler:
@FXML
private void performAction(ActionEvent e) {
service.doAction(...);
}
}
마지막으로 수행 다음은 방법을 보여줍니다 (당신에게 얼마나 추악한 일 봄 당신을 위해하고있는의 아이디어를 줄 것이다!) afterburner.fx은 매우 가볍고 (모든 최선의 방법으로) JavaFX 관련 DI 프레임 워크입니다. (이는 컨벤션 오버 구성 방식을 사용합니다. FXML 파일 이름과 컨트롤러 클래스 이름 및 CSS 파일 이름을 일치 시키면 모든 것이 작동합니다.)