Der Artikel ist zwar schon älter, aber immer noch aktuell. Ich hab da vor kurzem auch noch dran herum editiert
Es hängt davon ab, was du machen möchtest. Wie kompliziert es sein soll und wie gut lesbar.
Ich habe bisher 5 Varianten ausprobiert:
1) Daten per Setter an die Controller weiterreichen. Wenn du dir in deiner obersten Klasse eine Instanz eines "Application Models" erstellst, das idealerweise Gebrauch von JavaFX-Properties (für Databinding) macht, kannst du dies implizit alles darüber steuern. Du musst nur das Modell noch in den Controller bringen. Beispielsweise so, wie hier beschrieben:
http://www.java-forum.org/thema/methode-nach-initialize-aufrufen.172667/
Vorteil: Einfach umzusetzen. Leichtgewichtig. Wenn man für seine Controller Interfaces verwendet auch nachvollziehbar und eventuell kann man die ControllerFactory (a.k.a. das am FXMLLoader zu registrierende Callback) auch wiederverwenden (auch weiter injizieren).
Nachteil: Oldskool und vieeeeel zu simpel!
2) EventBus (wird kurz auf StackOverflow) genannt. Einen halbwegs gescheiten und flexiblen Eventbus kann man sich recht schnell zusammenschrauben. Es gibt sicher auch gute minimalistische Bibliotheken dafür.
Nachteil, wie ich finde: Ist bei kleinen Anwendung mit wenigen Daten, noch gut zu händeln. Artet die Anwendung aus (unsere hat jetzt knapp 20'000 Zeilen), kann die Übersichtlichkeit darunter leiden.
Vorteil: Sehr lose Kopplung der Komponenten.
3) Spring Boot - Dependency Injection: Das Projekt, dass ich dort gemacht hab, war eigentlich nur zum Spass. Hab versucht eine paralell entwickelte Web-Anwendung als Desktop-Anwendung nachzubauen. Natürlich mit Maven, natürlich mit Native Bundle Build
(sprich: Am Ende kommt eine eigenständige Applikation mit gebundeltem JRE raus - siehe
javapackager).
Vorteil: Kann man wunderbar Komponenten voneinander trennen. MVC oder MVVM lassen sich gut umsetzen.
Nachteil: Spring Boot ist schon recht heavy. Kann sein, dass es den Startvorgang unnötig verlängert. Kommt mir zumindest so vor.
4) Guice. Gestern mal probiert, weil ich es immer mal machen wollte. Nachdem ich kapiert hab, wie ich am besten einen FXMLLoaderService erstelle (das habe ich bei der SpringBoot-Variante gelernt), war es eine Sache von 30 Minuten (auch wenn ich Guice noch nicht gut genug kenne, um damit ein Pro zu sein).
Nachteil: Fällt mir gerade keiner ein.
Vorteil: Dependency-Injection-Leichtgewicht. (siehe Nachteil Spring Boot)
5) Eclipse e4 Dependency Injection / Declarative Services: Ist am längsten her. Hier eine Anwendung ohne das sonst übliche e4 "Gerümpel" (e4 kann sehr stark von der UI abstrahieren und braucht dann spezielle Renderer für ein konkretes GUI-Framework wie Swing/AWT, SWT oder JavaFX) zu bauen, ist recht aufwendig. Aber dank extrem loser Kopllung und der Möglichkeit Plugins out of the Box zu ermöglichen und zur Laufzeit hinzuzufügen oder zu entfernen, ist schon eine feine Sache.
Vorteil: Flexibel bis zum umfallen!
Nachteil: Eclipse-Doku... Mühsam. Initial recht hoher Aufwand, ab da aber recht einfach.
Für alles ausser 1 und 5 kann ich Code-Schnipsel liefern (1 nicht, weil bereits im Forum diskutiert, 5 nicht, weil 3 Jahre alt und nicht gewartet). Zu 3 findet man etwas im StackOverflow-Artikel verlinkt. Kann es aber dennoch posten.