Java Maven Build-Lebenszyklus
Lerne Mavens drei Lebenszyklen und die Standard-Phasen — validate, compile, test, package, verify, install, deploy — und wie Plugin-Ziele an sie gebunden werden.
Ein Lebenszyklus ist Mavens zentrale Idee: Ein Projekt zu bauen ist kein beliebiger Haufen von Aufgaben, sondern eine geordnete Abfolge bekannter Phasen. Wenn du mvn package eingibst, nennst du keine einzelne Aktion — du bittest Maven, jede Phase bis einschließlich package der Reihe nach auszuführen. Diesen Ablauf zu verstehen und zu wissen, wie Plugin-Ziele daran gebunden werden, ist der Unterschied zwischen blindem Kopieren von Befehlen und dem echten Verständnis deines Builds.
Drei Lebenszyklen – und der eine, den du am häufigsten nutzt
Maven liefert drei eingebaute Lebenszyklen. Sie sind unabhängig voneinander — das Aufrufen einer Phase des einen löst keinen anderen aus.
| Lebenszyklus | Zweck | Wichtige Phasen |
|---|---|---|
clean | Build-Ausgaben entfernen | pre-clean, clean, post-clean |
default | Projekt bauen und deployen | validate … compile … test … package … install … deploy |
site | Projektdokumentation generieren | pre-site, site, site-deploy |
Der default-Lebenszyklus ist der Ort, wo die eigentliche Arbeit stattfindet. Das mvn clean install, das du überall siehst, sind einfach zwei Lebenszyklen in einem Befehl: die clean-Phase aus dem Clean-Lebenszyklus, gefolgt von der install-Phase aus dem Default-Lebenszyklus.
Die Phasen des Default-Lebenszyklus
Der Default-Lebenszyklus hat 23 Phasen, aber sieben tragen die Last fast jedes Builds. Sie laufen immer in dieser Reihenfolge ab:
| Phase | Was sie tut |
|---|---|
validate | Prüft, ob das Projekt korrekt ist und alle benötigten Informationen verfügbar sind |
compile | Kompiliert den Hauptquellcode des Projekts |
test | Führt Unit-Tests mit einem geeigneten Framework aus (erfordert kein Packaging) |
package | Bündelt kompilierten Code in ein verteilbares Format, z. B. ein JAR |
verify | Führt Prüfungen der Integrationstestergebnisse durch, um die Qualität zu bestätigen |
install | Kopiert das Paket in das lokale Repository (~/.m2) für andere lokale Projekte |
deploy | Lädt das Paket in ein Remote-Repository zum Teilen hoch |
Die Regel, die alles regiert: Das Ausführen einer Phase führt diese Phase und alle vorangehenden Phasen aus. Daher führt mvn package zunächst still validate, compile und test aus. Es gibt keine Möglichkeit, „vorwärts zu springen" — du kannst nur früher aufhören.
mvn validate # just the sanity checks
mvn compile # validate -> compile
mvn test # validate -> compile -> test
mvn package # ... -> test -> package (produces target/app-1.0.jar)
mvn install # ... -> package -> verify -> install (now in ~/.m2)
mvn deploy # the full pipeline, ending with an uploadPhasen sind leer, bis Plugins Ziele an sie binden
Eine Phase ist nur ein Name und eine Position in der Abfolge — sie erledigt selbst keine Arbeit. Die Arbeit übernehmen Plugin-Ziele, die an Phasen gebunden sind. Ein Ziel wird als plugin:goal geschrieben, z. B. compiler:compile. Für ein Projekt, dessen <packaging> jar ist, liefert Maven einen sinnvollen Standardsatz von Bindungen:
| Phase | Standard-gebundenes Ziel |
|---|---|
compile | maven-compiler-plugin:compile |
test | maven-surefire-plugin:test |
package | maven-jar-plugin:jar |
install | maven-install-plugin:install |
deploy | maven-deploy-plugin:deploy |
Du kannst eigene Bindungen in pom.xml hinzufügen. Hier wird das exec-Plugin an die verify-Phase gebunden, sodass es automatisch gegen Ende des Builds ausgeführt wird:
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>smoke-test</id>
<phase>verify</phase>
<goals><goal>java</goal></goals>
</execution>
</executions>
</plugin>
</plugins>
</build>Du kannst ein Ziel auch direkt aufrufen, außerhalb jeder Phase — mvn compiler:compile führt nur dieses Ziel aus und überspringt den Lebenszyklus vollständig. Das ist gelegentlich nützlich, aber im Alltag rufst du Phasen auf und lässt die Bindungen feuern.
Ein praktisches Beispiel: Den Lebenszyklus simulieren
Maven selbst ist auf diesem Runner nicht installiert, daher modellieren wir den Lebenszyklus in reinem Java, um seine Regeln greifbar zu machen. Das Programm listet die Standard-Phasen auf, erfasst das an jede gebundene plugin:goal und „führt" dann mvn install aus — es führt jede Phase von validate bis install aus und beweist, dass deploy und clean nicht einbezogen werden.
Was man aus dem Durchlauf mitnehmen sollte:
- Die Ausgabe beginnt bei
validateund endet beiinstall— sechs Phasen für einen Befehl. Das ist die kumulative Regel in Aktion:mvn installist eine Kurzform für das Ausführen des gesamten Präfixes der Abfolge bisinstall, niemals nur die einzelne benannte Phase. - Jede ausgeführte Phase gab das daran gebundene
plugin:goalaus (compile -> compiler:compile,package -> jar:jarusw.). Phasen sind Slots; die Ziele sind das, was tatsächlich kompiliert, testet und bündelt.validategab(no goal bound)aus und zeigt, dass eine Phase ausgeführt werden kann, ohne etwas zu tun. deploy skipped : truebestätigt, dass Phasen nach der angeforderten niemals ausgeführt werden. Um in ein Remote-Repository zu veröffentlichen, musst du explizitmvn deployangeben; ein einfachesinstallbleibt bewusst lokal.clean ran : falsebeweist, dasscleanzu einem separaten Lebenszyklus gehört. Das Aufrufen voninstalllöschttarget/nicht, was genau der Grund ist, warummvn clean installbeide explizit nennt — eine Phase aus jedem Lebenszyklus.- Die Phasen liefen in der festen Reihenfolge
validate, compile, test, package, verify, installab, und das Programm endete mitBUILD SUCCESS. Die Reihenfolge ist nicht verhandelbar; Mavens Convention-over-Configuration-Versprechen beruht auf dieser garantierten, wiederholbaren Abfolge.
Häufige Befehle in der Praxis
Eine Handvoll Aufrufe deckt fast die gesamte tägliche Arbeit ab:
mvn clean # delete target/
mvn test # build and run unit tests
mvn package -DskipTests # build the JAR without running tests
mvn clean install # fresh build, install to local ~/.m2
mvn clean verify # CI's favourite: build + unit + integration checks-DskipTests kompiliert Tests, führt sie aber nicht aus; -Dmaven.test.skip=true überspringt auch ihre Kompilierung. Greife zum ersten, wenn Tests langsam sind, aber dennoch kompiliert werden sollen, und zum zweiten nur, wenn du sie wirklich vollständig aus dem Weg haben möchtest.
Wie geht es weiter
- Neu bei dem Tool? Starte mit der Maven-Einführung und lies dann, wie das POM Plugins und Bindungen deklariert.
- Phasen wie
compileundpackagekönnen nur erfolgreich sein, wenn die Bibliotheken des Projekts aufgelöst sind — sieh dir das Verwalten von Abhängigkeiten an. - Bevorzugst du ein Task-Graph-Modell gegenüber einer festen Phasenabfolge? Vergleiche mit der Gradle-Einführung.