gpt4 book ai didi

java - 如何通过 Spring XML 配置文件将 Spring bean Autowiring 到 FXML Controller 类中

转载 作者:行者123 更新时间:2023-11-30 03:15:14 34 4
gpt4 key购买 nike

我有一个 FXML Controller ,它具有一些 Spring Bean 依赖项。我找不到在加载 Controller 之前及时 Autowiring 它们的方法,因为我使用的是自定义 FXML 加载器:

@Bean
@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS, value = "prototype")
public UserProfile attachDocController() throws IOException {
return (UserProfile) loadController("/myproject/Forms/userProfile.fxml");
}

FXMLLoader loader = null;

protected Object loadController(String url) throws IOException {
loader = new FXMLLoader(getClass().getResource(url));
loader.load();
return loader.getController();
}

使用这种方法,我只能通过 @Autowired 注释直接注入(inject) bean 来 Autowiring bean:

public class UserProfile {

@Autowired
MyDependency myDependency;

这使我对 Spring 产生依赖,并在以后给我带来代码可维护性问题。如何将 Spring XML 文件配置中的依赖项 Autowiring 到 FXML Controller 类中?像这样的东西:

<bean id="UserProfile" class="myproject.controllerinjection.UserProfile" scope="prototype">
<aop:scoped-proxy proxy-target-class="true"/>

<property name="myDependency" ref="myDependency" />
</bean>

<bean id="myDependency" class="myproject.controllerinjection.MyDependency" scope="prototype">
<aop:scoped-proxy proxy-target-class="true"/>
</bean>

随着项目规模的扩大,考虑到长期项目的可维护性,这似乎是一条更好的路线。

更新:

我不太习惯 Lambda 表达式。我进行了一些研究,但整合了 @James_D 的建议,如下所示:

protected Object loadBeanController(String url) throws IOException {
loader = new FXMLLoader(getClass().getResource(url));
ApplicationContext ctx = WakiliProject.getCtx();

if (ctx != null) {
System.out.println("Load Bean...............");
loader.setControllerFactory(ctx::getBean);

} else {
System.out.println("No App.ctx...............");
}

return loader.getController();
}
每当我尝试调用 MyDependency 的方法时,

都会给出一个空指针。 MyDependency myDependency 永远不会被注入(inject)到 UserProfile 中。

最佳答案

当您调用FXMLLoader.load()时,它加载 FXML 文件。如果有fx:controller属性,它根据指定的类创建一个 Controller (并将 fx:id 属性元素注入(inject)该 Controller 实例等)。然后加载程序返回 FXML 文件的根目录。该 Controller 本质上链接到该 FXML 根。

默认情况下,FXMLLoader通过反射将 Controller 类映射到实例,调用 controllerClass.newInstance() (它有效地调用 Controller 类的无参数构造函数)。您可以通过指定controllerFactory来配置它,覆盖默认行为。关于FXMLLoader .

controllerFactory是一个映射 Class<?> 的函数对象(根据 fx:controller 属性中指定的类名构造)到 Controller 实例。如果您使用 Spring 来管理 Controller 实例,则只需要此函数来要求 Spring 应用程序上下文(bean 工厂)为您生成 Controller 实例。所以你基本上可以做 fxmlLoader.setControllerFactory(applicationContext::getBean); 。通过此设置,只需通过FXMLLoader加载fxml文件即可。将导致 FXMLLoader从应用程序上下文请求 Controller 类。可以通过 Spring 允许的任何方式配置应用程序上下文。

所以你的配置可以是这样的

@Configuration
public class Config {
@Bean
@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS, value = "prototype")
public UserProfile attachDocController() throws IOException {
return new UserProfile();
}
}

当然,您现在可以在配置类中注入(inject)依赖项:

    @Bean
@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS, value = "prototype")
public UserProfile attachDocController(MyDependency myDependency) throws IOException {
return new UserProfile(myDependency);
}

@Bean
public MyDependency createDependency() {
return new MyDependencyImpl();
}

然后在你的 UI 工作中你就可以做

FXMLLoader loader = new FXMLLoader(getClass().getResource("/myproject/Forms/userProfile.fxml"));
loader.setControllerFactory(applicationContext::getBean);
Parent root = loader.load();

// since everything can be initialized in the controller by D.I., you
// shouldn't need to access it, but if you do for some reason you can do

UserProfile controller = loader.getController();

哪里applicationContext是您的 Spring 应用程序上下文。无论应用程序上下文使用 XML 配置、基于注释的配置还是 Java 配置,这都有效。

更新

如果由于某种原因您无法使用 Java 8 或更高版本,请调用 setControllerFactory与 Java 7 兼容的看起来像:

loader.setControllerFactory(new Callback<Class<?>, Object>() {
@Override
public Object call(Class<?> c) {
return applicationContext.getBean(c);
}
});

您需要applicationContext是一个字段或 final本地变量,以便在 Java 7 中工作。请注意,在撰写本文时,Oracle 尚未公开支持 Java 7。

关于java - 如何通过 Spring XML 配置文件将 Spring bean Autowiring 到 FXML Controller 类中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32789528/

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