Java 9 und Dependency Injection - Wo ist das Problem?

Seit Ende September ist nun das SDK von Java 9 veröffentlicht. Die Verzögerung von Major Releases hat leider eine lange Tradition und ist auch bei diesem Release eingetreten. Einer der Gründe hierfür war das Teilprojekt Jigsaw, dass für Modularisierung im Java-Umfeld sorgen soll.

Teil dieser Modularisierung ist auch die konsequente Beschränkung der reflektiven Zugriffe zur Laufzeit auf fremde Module

Auf der anderen Seite nutzen zahlreiche Frameworks Reflektion um in der Laufzeitumgebung zentrale Funktionen bereitzustellen. Auch die Dependency Injection ist hier ein typischer Anwendungsfall:

Stellen wir uns folgendes Szenario vor: Wir haben eine Bean namens Person, die Vorname und Nachname kapselt. Zusätzlich wirft sie PropertyChangeEvents sobald sich eine der beiden Eigenschaften ändert.

Die Klasse könnte wie folgt aussehen:

public class Person
{
private String firstName;
private String familyName;
@Inject
private EventBus eventBus;
public void setFamilyName(String familyName) {
PropertyChangeEvent event = new PropertyChangeEvent(this,"familyName",
this.familyName,familyName);
this.familyName = familyName;
eventBus.publishEvent(event);
}
public String getFamilyName() {
return familyName;
}
...
}

Hierbei wird in jede Instanz der Klasse Person ein Objekt der Klasse EventBus injiziert. Dieser Event Bus nimmt anschließend die PropertyChangeEvents, die in den Setter-Methoden erzeugt werden, über die Methode publishEvent() entgegen.

Betrachtet man den Quellcode dieser Klasse, muss man sich allerdings fragen, wie das funktionieren soll. Immerhin wird die Instanzvariable “eventBus” niemals mit einem Wert belegt und sie ist darüber hinaus auch noch als private markiert. Lediglich die Annotation “@Inject” liefert den Hinweis darauf, dass hier etwas injiziert werden soll.

Des Geheimnis Lösung ist in der Reflection API von Java zu finden. Mit ihr kann man tatsächlich zur Laufzeit die Instanzvariablen einer Klasse lesen und schreiben unter Missachtung der Sichtbarkeiten wie sie durch die Schlüsselwörter (public, protected, private) vorgegeben werden. Zwar muss man sich hierfür durch einige sehr explizite Aufrufe und unter Beachtung diverser Exceptions zunächst den Zugriff gestatten, letztendlich wird dies aber in der Standard-Laufzeitumgebung gestattet, weil alle möglichen Beschränkungen in Bezug auf die Reflection API per default inaktiv sind.

Und hier wollte das Projekt Jigsaw für Verbesserung sorgen. Man wollte unter Anderem den reflektiven Zugriff auf private Instanzvariablen von Klassen fremder Module unterbinden. Immerhin hat der Entwickler einer solchen Klasse ja in voller Absicht die entsprechende Variable als privat und als von außen nicht zugreifbar markiert.

Schade ist hier nur, dass dann nicht die Injektion von Abhängigkeiten wie im oben genannten Beispiel erfolgen kann, wenn sie etwaige Modulgrenzen überschreiten soll.

Dieses Problem führte u.a. dazu, dass es Querelen um die Zustimmung von Jigsaw gab. Das nun letztendlich doch zum Release 9 des JDK mit Jigsaw kam, ist dem Kompromiss zu verdanken, dass der illegale Zugriff per Reflektion auf modulfremde Klassen nun per default zulässig ist.

Man sollte sich aber schon die Frage stellen, ob es denn keinen sauberen Weg für die Dependency Injection, die dem Entwickler ja ohne Frage viel Arbeit abnimmt, gibt.

Im nächsten Teil dieses Blogs, werde ich einige Alternativen zu Dependency Injection mittels Reflection API vorstellen.


Hamburg - Lead Software Developer

Kontaktieren Sie uns jetzt

Engel & Völkers Technology
E-Mail
Zurück
Kontakt
Tragen Sie hier Ihre Kontaktdaten ein
Vielen Dank für Ihre Nachricht. Wir werden uns umgehend um Ihr Anliegen kümmern und uns schnellstmöglich bei Ihnen melden.

Ihr Engel & Völkers Team
Anrede
  • Herr
  • Frau
Absenden

Folgen Sie uns auf Social Media


Array
(
[EUNDV] => Array
(
[67d842e2b887a402186a2820b1713d693dd854a5_csrf_offer-form] => MTM5MjE5NzU3NkJ4d29xancwTDVhZWFIRzEycXAxcW9SdElHdVBqMTdV
[67d842e2b887a402186a2820b1713d693dd854a5_csrf_contact-form] => MTM5MjE5NzU3NnlHcUR0Y2VlTXVPUndLMHZkMW9zMnRmRlgxaUcwaFVG
)
)