在
FXMLLoader.load(URL,ResourceBundle)您所呼叫的方法是一种
static方法-
因此它实际上不关注了
FXMLLoader你化实例,以及因此忽略了
controllerFactory它引用您的Spring bean工厂。
重写您的
SpringFXMLLoader类,如下所示:
public class SpringFxmlLoader { private static final ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringApplicationConfig.class); public Object load(String url, String resources) { FXMLLoader loader = new FXMLLoader(); loader.setControllerFactory(clazz -> applicationContext.getBean(clazz)); loader.setLocation(getClass().getResource(url)); loader.setResources(ResourceBundle.getBundle(resources)); try { return loader.load(); } catch (IOException e) { e.printStackTrace(); } return null; }}这使用 实例
方法
loader.load(),它将使用您的控制器工厂:即它将使用Spring实例化控制器。
您看到两次加载控制器的原因是,默认情况下,bean工厂赋予了控制器单例作用域并使其急切地创建,因此,一旦创建bean
factory(
applicationContext),它就会创建一个控制器。该控制器将进行
dataProvider初始化(当然,但仅 在
构造函数完成 之后 )。然后,对静态
FXMLLoader.load(...)方法的调用通过通常的机制(即,通过调用其no-
arg构造函数)创建第二个控制器。该实例将不会
dataProvider在任何时候进行初始化。
顺便说一句,您可能不希望控制器成为单例。如果要两次加载FXML文件,以获取的两个实例,则
Parent可能需要每个实例都有其自己的控制器,否则会发生奇怪的行为。我建议将控制器作为原型(这意味着Bean工厂将在每次请求实例时创建一个新实例,而不是重用单个实例)。您可以在config类中执行以下操作:
@Configuration@ComponentScan(basePackages = {"mycompany.imageviewer.controller", "mycompany.imageviewer.dataprovider.impl" })public class SpringApplicationConfig { private static final Logger LOG = Logger.getLogger(SpringApplicationConfig.class); @Bean public DataProvider dataProvider() { LOG.debug("Initializing dataProvider via SpringApplicationConfig"); return new DataProviderImpl(); } @Bean @Scope("prototype") public ImageViewerController imageViewerController() { LOG.debug("Initializing ImageViewerController via SpringApplicationConfig"); return new ImageViewerController(); }}


