Der generierte Mapping-Code nutzt keine Reflection, sondern Getter- und Setter-Aufrufe – und erreicht damit die Geschwindigkeit von handgeschriebenem Mapping-Code. Ganz nebenbei ist der generierte Code lesbar und verständlich. Das ist wichtig, falls der Projektverantwortliche Angst hat, ein weiteres Werkzeug ins Projekt einzubinden – zur Not stellt man den generierten Code unter Versionskontrolle und pflegt ihn später von Hand weiter (wer einmal MapStruct verwendet hat, wird das aber nicht wollen ;-).
MapStruct wird als Annotations-Prozessor eingebunden, d.h. der Mapping-Code wird beim Aufruf von
javac
(bzw. bei jedem Speichern z.B. in Eclipse) generiert. Das Prozessor-JAR wird dabei nur zur Compile-Zeit benötigt. Zur Laufzeit ist bei einem Komponentenmodell wie CDI gar kein JAR als Abhängigkeit nötig, ohne Komponentenmodell nur ein winziges JAR < 20 K.Folgender Code reicht, um den Mapping-Code zwischen einer Kunde-Entity und einem Kunde-DTO generieren zu lassen:
@Mapper(componentModel = "cdi") public interface KundeMapper { @Mapping(target = "geburtsdatum", format = "dd.MM.yyyy") KundeDTO jpaEntity2RestDto(Kunde kunde); }
MapStruct erzeugt daraus in etwa folgenden Code:
@Generated("org.mapstruct.ap.MappingProcessor") @ApplicationScoped public class KundeMapperImpl implements KundeMapper { public KundeDTO jpaEntity2RestDto(Kunde kunde) { // null-Checks // Ziel-Objekt-Erzeugung // Getter-/Setter-Aufrufe // ... } }
Der standardmäßig generierte Code ist oft schon genau das, was man benötigt. Ansonsten ist so ziemlich alles konfigurierbar: Unterschiedliche Property-Namen in Quell- und Ziel-Bean, unterschiedliche Typen, die Objekt-Fabriken zur Ziel-Objekt-Erzeugung... Zudem können vorhandene, handgeschriebene Mapper eingebunden werden. Und Objekt-Graphen werden selbstverständlich genauso gemappt wie Collections, Maps, Arrays... Für JAXB, Joda-Time und Java 8 Date&Time stehen automatische Mappings zur Verfügung.
Man merkt, dass dieser Mapper mit vielen Praxis-Problemen im Hinterkopf entwickelt wurde. Und man fragt sich relativ schnell, warum man nur so lange das Bean-Mapping von Hand oder mit Reflection-Bibliotheken durchgeführt hat ;-)
Mindestvoraussetzung für MapStruct ist Java 6 – aber da heute der letzte Tag der kostenfreien Java-7-Updates (und ab morgen nur noch Java 8 "aktuell") ist, sollte das kein Problem darstellen.
Die Folien zu meinem Vortrag finden sich hier.