W3docs

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.

LebenszyklusZweckWichtige Phasen
cleanBuild-Ausgaben entfernenpre-clean, clean, post-clean
defaultProjekt bauen und deployenvalidatecompiletestpackageinstalldeploy
siteProjektdokumentation generierenpre-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:

PhaseWas sie tut
validatePrüft, ob das Projekt korrekt ist und alle benötigten Informationen verfügbar sind
compileKompiliert den Hauptquellcode des Projekts
testFührt Unit-Tests mit einem geeigneten Framework aus (erfordert kein Packaging)
packageBündelt kompilierten Code in ein verteilbares Format, z. B. ein JAR
verifyFührt Prüfungen der Integrationstestergebnisse durch, um die Qualität zu bestätigen
installKopiert das Paket in das lokale Repository (~/.m2) für andere lokale Projekte
deployLä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 upload

Phasen 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:

PhaseStandard-gebundenes Ziel
compilemaven-compiler-plugin:compile
testmaven-surefire-plugin:test
packagemaven-jar-plugin:jar
installmaven-install-plugin:install
deploymaven-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.

java— editable, runs on the server

Was man aus dem Durchlauf mitnehmen sollte:

  • Die Ausgabe beginnt bei validate und endet bei install — sechs Phasen für einen Befehl. Das ist die kumulative Regel in Aktion: mvn install ist eine Kurzform für das Ausführen des gesamten Präfixes der Abfolge bis install, niemals nur die einzelne benannte Phase.
  • Jede ausgeführte Phase gab das daran gebundene plugin:goal aus (compile -> compiler:compile, package -> jar:jar usw.). Phasen sind Slots; die Ziele sind das, was tatsächlich kompiliert, testet und bündelt. validate gab (no goal bound) aus und zeigt, dass eine Phase ausgeführt werden kann, ohne etwas zu tun.
  • deploy skipped : true bestätigt, dass Phasen nach der angeforderten niemals ausgeführt werden. Um in ein Remote-Repository zu veröffentlichen, musst du explizit mvn deploy angeben; ein einfaches install bleibt bewusst lokal.
  • clean ran : false beweist, dass clean zu einem separaten Lebenszyklus gehört. Das Aufrufen von install löscht target/ nicht, was genau der Grund ist, warum mvn clean install beide explizit nennt — eine Phase aus jedem Lebenszyklus.
  • Die Phasen liefen in der festen Reihenfolge validate, compile, test, package, verify, install ab, und das Programm endete mit BUILD 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 compile und package kö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.

Übungen

Übung
Was macht 'mvn package' in einem Standard-Maven-JAR-Projekt?
Was macht 'mvn package' in einem Standard-Maven-JAR-Projekt?
Was this page helpful?