我想initialize在创建时自动调用控制器的方法之前在控制器中设置一些非 UI 字段。据我了解,这样做的方式是定制的提供ControllerFactory,因为initialize()被调用后 ControllerFactory返回创建的对象。我想根据这个答案使用以下代码:FXMLLoader loader = new FXMLLoader(mainFXML); // some .fxml file to loadloader.setControllerFactory(param -> { Object controller = null; try { controller = ReflectUtil.newInstance(param); // this is default behaviour } catch (InstantiationException | IllegalAccessException e) { e.printStackTrace(); } if (controller instanceof Swappable) { ((Swappable) controller).setSwapper(swapper); // this is what I want to add } return controller;});但是,ReflectUtil该类(在 default setControllerFactory method 中使用)是com.sun.reflect.misc包的一部分,我无法使用它,因为编译失败并带有error: package sun.reflect.misc does not exist.据我了解,我不能使用 sun 包,因为这不是公共 API。所以问题是:我该怎么办?我找不到任何其他示例,只有带有 ReflectUtil 的示例,而且,我希望我ControllerFactory能够使用 @FXML 注释来遵守 JavaFX 的默认工作流等等,这是否可以与其他一些 DI 框架(如 Jodd Petite)一起使用,例如?还有其他方法可以设置字段吗?(除了同步它并等待initialize()直到从其他线程调用 setter 方法)。 github 上的完整代码用于上下文。
2 回答
饮歌长啸
TA贡献1951条经验 获得超3个赞
如果要通过反射创建实例,则需要使用1后跟.Class.getConstructor(Class...)
Constructor.newInstance(Object...)
FXMLLoader loader = new FXMLLoader(/* some location */);loader.setControllerFactory(param -> { Object controller; try { controller = param.getConstructor().newInstance(); } catch (ReflectiveOperationException ex) { throw new RuntimeException(ex); } if (controller instanceof Swappable) { ((Swappable) controller).setSwapper(swapper); } return controller;}
此代码要求您的控制器类具有公共的无参数构造函数。如果您想通过构造函数注入您的依赖项,您可以执行以下操作:
FXMLLoader loader = new FXMLLoader(/* some location */);loader.setControllerFactory(param -> { Object controller; try { if (Swappable.class.isAssignableFrom(param)) { controller = param.getConstructor(Swapper.class).newInstance(swapper); } else { controller = param.getConstructor().newInstance(); } } catch (ReflectiveOperationException ex) { throw new RuntimeException(ex); } return controller;}
此代码假定 的所有子类Swappable
都有一个公共的单参数构造函数,该构造函数采用Swapper
.
如果您想获得非公共构造函数,则需要使用Constructor.getDeclaredConstructor(Class...)
. 然后你需要调用setAccessible(true)
在Constructor
调用它之前。
如果使用 Jigsaw 模块(Java 9+)并且此控制器工厂代码与控制器类不在同一个模块中,则需要记住一些事情。假设控制器工厂代码在 module 中foo
,控制器类在 module 中bar
:
如果使用的是公共控制器的公共构造则
bar
必须exports
控制器类的包至少foo
如果使用非公共控制器和/或构造函数,则必须发生同样的事情,但使用
opens
而不是exports
否则会抛出异常。
1.如果使用无参数(不一定是公共)构造函数,您可以绕过getConstructor
并Class.newInstance()
直接调用。但是,请注意,此方法存在问题,并且自 Java 9 以来已被弃用。
添加回答
举报
0/150
提交
取消