gpt4 book ai didi

java - 依赖注入(inject)和 JavaFX

转载 作者:太空宇宙 更新时间:2023-11-04 10:44:08 26 4
gpt4 key购买 nike

由于 JavaFX 运行时想要实例化我的应用程序对象和所有 Controller 对象,我如何将依赖项注入(inject)到这些对象中?

如果对象由 DI 框架(如 Spring)实例化,该框架将连接所有依赖项。如果我手动实例化对象,我将通过构造函数参数提供依赖项。但是我应该在 JavaFX 应用程序中做什么?

谢谢!

最佳答案

您可以指定controller factory对于FXMLLoader 。 Controller 工厂是一个将 Controller 类映射到将用作 Controller 的对象(可能但不一定是该类的实例)的函数。

因此,如果您希望 Spring 为您创建 Controller 实例,这可以很简单:

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将为 Class<?> c 创建 Controller 实例通过调用 context.getBean(c); .

因此,例如,您可以有一个配置:

@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(...);
}
}

如果您没有使用 DI 框架,并且想要“手动”进行注入(inject),则可以这样做,但它涉及使用大量反射。下面展示了如何实现(并且会让您了解 Spring 为您做了多少丑陋的工作!):<​​/p>

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 文件名与 Controller 类名以及可选的 CSS 文件名相匹配,一切就正常了。)

关于java - 依赖注入(inject)和 JavaFX,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48607726/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com