2.1.2. Dependency Injection
Das Modul injection ist ein kleiner typbasierter Container. Es scannt ein Paket, erkennt markierte Klassen, hält deren gemeinsame Instanzen und füllt Abhängigkeiten. fx verwendet es für Controller, Components und Converter. JavaFX ist für den Container selbst nicht erforderlich.
Nach der lokalen Installation des Bibliotheks-Reactors aus dem Schnellstart genügt diese Dependency:
<dependency>
<groupId>de.neitzel.lib</groupId>
<artifactId>injection</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
Das Modul bringt Reflections 0.10.2, jakarta.inject-api 2.0.1 und gemeinsame Logging-Abhängigkeiten mit. Die Bibliothek setzt Java 21 voraus. Es handelt sich um lokale Entwicklungsartefakte, nicht um eine hier vorausgesetzte Central-Veröffentlichung.
Die folgenden öffentlichen Klassen liegen jeweils in einer eigenen Datei im Paket example.services:
package example.services;
@jakarta.inject.Singleton
public class Greeting {
public String text() { return "Hello"; }
}
package example.services;
@jakarta.inject.Named
public class Printer {
private final Greeting greeting;
public Printer(Greeting greeting) { this.greeting = greeting; }
public void print() { System.out.println(greeting.text()); }
}
package example.services;
import de.neitzel.injection.ApplicationContext;
public class Main {
public static void main(String[] args) {
var context = new ApplicationContext("example.services");
context.getComponent(Printer.class).print();
context.createComponent(Printer.class).print();
}
}
Der einzige Konstruktor wird auch ohne @Inject verwendet. getComponent liefert die gemeinsame Printer-Instanz. createComponent erzeugt einen neuen Printer, injiziert aber denselben Greeting-Singleton. Beide Aufrufe geben Hello aus. Einen vollständigen Maven-POM zeigt der JavaFX-Schnellstart; für dieses reine Java-Beispiel werden statt fx nur injection und ein gewöhnlicher Java-Start benötigt.
ApplicationContext context = new ApplicationContext(DeskApp.class);
LoadedView loaded = ViewLoader.load(
DeskController.class.getResource("Desk.fxml"), DeskApp.sample(), context);
DeskApp trägt @Config(basePackage = "de.neitzel.fx.example"). Der ViewLoader fordert Controller, Forms und Converter aus diesem Kontext an. AgeSuffix ist @Named; AgeConverter erhält ihn im Konstruktor. StreetConverter injiziert StreetPolicy in ein privates Feld, und AddressForm erhält FormHeading über einen Setter.
| Stelle | Beispiel | Zeitpunkt |
|---|---|---|
| Konstruktor | AgeConverter(AgeSuffix) |
Beim Erzeugen |
| Feld | StreetConverter.policy |
Nach dem Konstruktor |
| Setter | AddressForm.setHeading |
Nach den Feldern |
JavaFX initialize |
AddressForm übernimmt Heading-Text | Erst später beim FXML-Laden |
VisitRow erhält denselben DeskController für jede frisch erzeugte Tabellenzeile. NeitzelLib-ViewModels selbst entstehen dagegen durch die FX-Runtime, nicht im Container.
Die Referenz beschreibt Scan-Grenzen, Konstruktorwahl, Supertypen, Fehler, manuelle Registrierung und die Low-Level-Metadaten. Der Container besitzt keine Qualifier-Auflösung, Producer, Lifecycle-Hooks oder automatische Ressourcenfreigabe. Diese Grenzen sind bei einer Anwendung wichtiger als die bloße Annotation einer Klasse.