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.
