Stefan Zörner
10.10.2022
Anwendungen mit einer bloßen Programmiersprache zu entwickeln wäre mühsam. Bibliotheken und Frameworks machen das Leben leichter. Erstere sind der Sprache als Standardbibliothek oft mitgegeben wie z.B. in C und C++. Entwicklungsvorhaben ergänzen sie durch weitere Bibliotheken und Frameworks – oft von Dritten, gerne Open Source. Das Spring Framework in Java blickt bereits auf eine 20-jährige Geschichte zurück.
Steckbrief: Spring Framework
Name: Spring Framework
Software-Gattung: Applikationsframework
Veröffentlicht: 2002 (Version 1.0 2004)
Herkunft/Ursprung: Interface21 (später VMWare), Open Source (Apache License)
Zielplattform: Java (JVM), plattformunabhängig
Programmiersprache(n): Java
Homepage: spring.io
Um die Jahrtausendwende war die Programmiersprache Java so weit ausgewachsen, dass Unternehmen begannen geschäftskritische Anwendungen auf dieser Basis zu realisieren. Sun Microsystems stellte Spezifikationen unter dem Label J2EE (Java 2 Enterprise Edition) bereit, die Hersteller wie z.B. IBM in ihre Produkte (vor allem Applikationsserver) gossen – wenig später kamen Open Source-Lösungen wie z.B. Apache Tomcat hinzu.
Das Interesse der Java-Entwicklergemeinde war groß, versprachen die Technologien doch einen verlässlichen und zugleich herstellerneutralen Rahmen für Mehrschichtanwendungen mit Web-Frontend und relationaler Datenbank, wie sie damals in großer Menge entstanden.
Mit wachsender Adoption mehrten sich kritische Stimmen. Die Entwicklerproduktivität sei zu gering. Zwar wären anspruchsvollste Dinge wie verteilte Transaktionen möglich, gleichzeitig gingen einfache Dinge nicht angemessen leicht von der Hand. Insbesondere das in J2EE enthaltene Komponentenmodell EJB (Enterprise JavaBeans) wurde diesbezüglich bemängelt.
Viel Sichtbarkeit und Zustimmung erhielt damals Rod Johnson, der in den Büchern „J2EE Design and Development“ [Joh02] und „J2EE Development without EJB“ [Joh+04] von seinen praktischen Erfahrungen mit J2EE berichtete und einzelne Aspekte kritisch hinterfragte. Vor allem zeigte er eine leichtgewichtige Alternative im Rahmen der Bücher und stellte sie als Quelltext zum Download bereit. Heute kennen wir es als Spring Framework.
Tabelle 1 zeigt wichtige Architekturziele von Spring; die Reihenfolge gibt eine grobe Orientierung bezüglich ihrer Wichtigkeit.
Ziel | Beschreibung (und zugehöriges Software-Qualitätsmerkmal) |
Hohe Entwickler-produktivität | Anwendungen auf Basis von Spring lassen sich effizient entwickeln. Java-Entwickler kommen gut mit dem Framework zurecht. Die dahinterliegenden Konzepte sind schnell verstanden und kein Hexenwerk. Entwickler konzentrieren sich auf die Fachlogik. (Wartbarkeit, Benutzbarkeit (aus Entwicklersicht)) |
Unternehmens- kritische Anwendungen ermöglichen | Spring erlaubt die Entwicklung von zuverlässigen und sicheren Applikationen, wie sie Unternehmen und Organisationen zur Unterstützung wichtiger Geschäftsfähigkeiten erwarten. (Zuverlässigkeit, Sicherheit) |
Auf lange Sicht wartbare Lösungen | Mit Spring realisierte Anwendungen sind leicht erweiterbar und änderbar. Genutzte Technologien (z.B. Bibliotheken, Middleware, Persistenz) lassen sich einfach aktualisieren und zu einem gewissen Grad auch austauschen. Das gilt insbesondere für Spring selbst. (Erweiterbarkeit. Änderbarkeit) |
Portable und kompatible Arbeitsergebnisse | Die Anwendungen sind auf allem relevanten Zielplattformen lauffähig (Applikationsserver wie z.B. WebSphere, Web-App-Server wie Tomcat, Standalone als Java-Prozess ...). Neue Java- oder Spring-Versionen brechen eine vorhandene Anwendung nicht. (Kompatibilität, Portierbarkeit) |
Zukunftsfähiges Framework | Spring kann dem technologischen Fortschritt folgen. Neue Produkte, Entwicklungsmethoden und Zielumgebungen sind rasch adaptiert. Die Entscheidung für Spring ist keine Sackgasse. (Wartbarkeit (des Frameworks selbst)) |
Mit welchen Lösungsansätzen erreichte Spring diese Ziele?
Als wichtiges Kernprinzip für die Entwicklerproduktivität betonte das Framework reines Java mit klassischer Objektorientierung; es vermied server-spezifische Komponentenmodelle wie EJB. Stattdessen waren POJOs (Plain Old Java Objects) die „Komponenten“ in Spring. Sie fordern keinerlei Abhängigkeit zu Spring selbst – diese „Nicht-Invasivität“ war neu für ein Framework. Der Ansatz erlaubte es auch Anwendungsteile direkt in der IDE zu testen statt in einem Applikationsserver; generell war die gute Unterstützung für Unit- und Integrationstests von Anfang an im Fokus.
Geradezu wegweisend in Spring war der Einsatz von Dependency Injection (DI, [Fow04]) zur Entkopplung der Anwendungsteile. Daneben kamen bekannte objektorientierte Entwurfsmuster zum Einsatz inkl. entsprechender Benennung (z.B. Prototype, Singleton). Dies und durchgängige Konzepte wie z.B. Templates zum Zugriff auf unterschiedlichste Technologien erleichterten den Einstieg ins Framework.
Für bei unternehmenskritischen Anwendungen wichtige Themen wie Transaktionen und Security setzte Spring auf Aspekt-orientierte Programmierung (AOP). Die POJOs wurden dabei mit Hilfe eines Decorator-Ansatzes mit den querschnittlichen Themen „umhüllt“ – betreffende Methoden der POJOs mit Berechtigungsprüfungen, Caching und ähnlichem „beratschlagt“, was auch eine klare Trennung von fachlichem und technischen Code ermöglichte. Später kamen eine AspectJ-Unterstützung und das Hinzufügen von Aspekten über Annotationen hinzu. Ein weiterer Baustein beim Entwickeln von zuverlässigen und sicheren Anwendungen war die Nutzung etablierter (Java-) Standards in diesem Bereich wie z.B. JDBC und JTA – wozu das Rad neu erfinden, wenn gute Lösungen vorhanden sind?
Für eine bessere Wartbarkeit der mit Spring realisierten Anwendungen wurde die Konfiguration in XML ausgelagert. Dies betraf den Vorrat der Komponenten, ihre Abhängigkeiten untereinander (Dependency Injection) und ihre Parametrisierung. Mit späteren Versionen kamen XML-Namespaces und andere Konfigurationsmöglichkeiten wie Java-Annotationen hinzu.
Die Templates vereinfachten den Zugriff auf Technologien wie beispielsweise relationale Datenbanken und verbargen komplizierte Details, etwa das Ressourcen-Management oder die Fehlerbehandlung. Dieses Integrationsmuster fand auch bei neueren Technologien immer wieder Verwendung und erleichtert Spring-Nutzern den Einstieg. Spring blieb dadurch am Puls der Zeit.
Abbildung 1 zeigt eine schematische Web-Applikation in Spring im Zusammenspiel mit den wesentlichen Spring-Lösungskonzepten.
Während Java EE-Server die Implementierungen für die enthaltenen Standards (z.B. JPA) üblicherweise mitbringen, setzte Spring darauf, diese in der Anwendung mitzuverpacken. Das führt zwar zu größeren Deployment-Einheiten, aber auch zu mehr Flexibilität. Teams konnten neuere Versionen von Bibliotheken und Frameworks nutzen, und diese auch Schritt für Schritt umstellen. Dieser Vorteil spielt heute eine untergeordnete Rolle, da Services eher als Standalone-Prozesse in ihrer eignen JVM laufen, als auf einem großen Cluster von Applikationsservern. Aber auch heute noch ist das Framework von spezifischen Java- und Server-Versionen so gut wie möglich entkoppelt. Die aktuelle Spring Version 5.3.x beispielsweise unterstützt die Java-Versionen JDK 8 bis 19, was einer Zeitspanne von immerhin acht Jahren entspricht (2014 – 2022). Das macht Upgrade-Entscheidungen für Anwender des Frameworks unabhängig planbar.
Der Funktionsumfang von Spring ist mit der Zeit stark gewachsen, vor allem da immer mehr Technologien in Spring-Manier integriert wurden. Aber kein Vorhaben braucht alles. Spring hat immer großen Wert darauf gelegt modular zu sein und es Teams zu ermöglichen nur Teile zu verwenden. Recht früh machte das Spring-Team diese Modularisierung auch explizit und lieferte das Framework kleinteilig aus. Aber Spring ist heute weitaus mehr als das Framework allein.
Die Abbildungen 3 und 4 machen dies eindrucksvoll sichtbar, indem sie das Spring Framework von 2004 der Spring-Welt von 2022 gegenüberstellen. Abbildung 3 ist der (ganz nebenbei von Anbeginn exzellenten) offiziellen Dokumentation nachempfunden und zeigt die Modularisierung des Frameworks mit seinen drei zentralen Themen: als Fundament den „Lightweight Container“ mit Konfiguration und Dependency Injection, zum zweiten die Aspekt-orientierte Programmierung und schließlich die Integration zahlreicher Technologien. Im Vordergrund stehen dabei die damals besonders relevanten Web- und Datenbanktechnologien.
In Abbildung 4 sehen wir das Spring-Ökosystem mit allen aktuellen (Stand Juli 2022, [Spring]), offiziellen Spring Projekten. Das Erscheinungsjahr der 1.0-Version (GA, General Availability) ist jeweils mit angegeben und lässt die Geschichte der Spring-Familie nacherleben. Das Framework selbst ist nur eine Kachel unter vielen. Die Integration von Technologien erfolgt in eigenen Projekten, was es Spring leichter macht dem technologischen Fortschritt zu folgen. Innovation erfolgt in Experimenten, die nicht immer erfolgreich sein müssen. Entsprechend fehlt ein Dutzend ehemaliger Spring-Projekte in der Abbildung, die mittlerweile eingestellt sind.
Abbildung 4 zeigt in verdichteter Form auch die Anzahl der durch die Community vergebenen Sterne für die einzelnen Spring-Projekte bei GitHub. Als Maß für die Relevanz gibt es nur eine Idee. Trotzdem schneiden die prominentesten Projekte gut dabei ab. Der Spitzenreiter Spring Boot hat aktuell mehr Sterne auf GitHub als das Framework selbst.
Womit wir im heute angekommen sind. Spring Boot ist angetreten, um Entwicklungsteams Orientierung zu geben in einem groß gewordenen Spring, das (gefühlt zu) viele Möglichkeiten anbietet Probleme zu lösen. Da das Spring-Team nicht einfach Features entfernen kann, um keine bestehenden Anwendungen zu brechen funktioniert eine XML-Konfiguration von 2002 auch noch in einer aktuellen Spring-Version. Aber würde man das heute noch so machen?
Spring Boot beschreibt eine moderne, meinungsbehaftete Art Spring-Anwendungen zu bauen und ist heute eine verbreitete Lösung zur Implementierung von Services in Java. Spring gehört auch im Zeitalter von Microservices und der Cloud nicht zum alten Eisen, auch wenn es durch neue Frameworks wie Quarkus in jüngster Zeit wieder Konkurrenz bekommt.
Als das Spring Framework vor zwanzig Jahren erschien läutete es eine kleine Revolution in der Java-Welt ein. Gemeinsam mit Hibernate trieb es die althergebrachten Ansätze der schwergewichtigen Java EE-Welt vor sich her und beeinflusste spätere Versionen davon stark. Nicht zuletzt hat Spring Dependency Injection salonfähig gemacht.
[Fow04] Martin Fowler: „Inversion of Control Containers and the Dependency Injection pattern”
[Joh02] Rod Johnson: „J2EE Design and Development”, Wiley 2002
[Joh+04] Rod Johnson, Jürgen Höller: „J2EE Development without EJB”, Wiley 2004
[Spring] Überblick: Spring-Projekte
Dieses Porträt ist ursprünglich in der IT Spektrum, Ausgabe 5 | 2022 als zweiter Teil einer Reihe über Architektur-Ikonen der Softwareentwicklung erschienen. Rückmeldungen aller Art gerne an mich per E-Mail. Insbesondere auch Wünsche für weitere Porträts.
Architektur-Porträt: Visual Studio Code
Architektur-Porträt: Corona-Warn-App
Architekturikonen in Software Überblick über alle Porträts