ANT vs Maven vs Gradle

Bevor wir uns mit ANT, Maven oder Gradle beschäftigen, müssen wir zunächst einige Dinge verstehen, die damit zusammenhängen.

Abhängigkeit: Im Allgemeinen bezieht sich eine Abhängigkeit darauf, dass etwas eine andere Sache benötigt, um selbst ausgeführt zu werden. Einfach ausgedrückt: „A“ ist von „B“ abhängig, wenn „A“ für seine erfolgreiche Ausführung „B“ benötigt. In der Welt der Software ist eine Abhängigkeit alles, was Ihre Anwendung für ihre erfolgreiche Ausführung benötigt. Es ist im Grunde jede externe Bibliothek, die von der Anwendung benötigt wird. z.B. zuul, hystrix, lombok, jdbc, etc.

Anfänglich haben wir Abhängigkeiten verwaltet, indem wir:

  • die jar-Datei der benötigten Bibliothek manuell aus dem Internet heruntergeladen und zu unserem Projekt hinzugefügt haben.
  • ein Skript geschrieben haben, das die Bibliothek automatisch von einer externen Quelle über das Netzwerk herunterlädt.

Probleme vor diesen Tools:

  • Das Hinzufügen der Abhängigkeiten durch manuelles Herunterladen aus dem Internet ist eine sehr anstrengende Aufgabe.
  • Unsere Skripte könnten fehlschlagen, wenn sich die URL der externen Quelle im Internet ändert.
  • Es ist sehr schwierig, die transitiven Abhängigkeiten in unserer Anwendung zu identifizieren und zu verwalten.

Dependency Management Tool: Es löst die für die Anwendung erforderlichen Abhängigkeiten auf und verwaltet sie.

Build-Tool: Es automatisiert die Erstellung von ausführbaren Anwendungen aus dem Quellcode. Das Erstellen umfasst das Kompilieren, Verknüpfen und Verpacken des Codes in eine brauchbare oder ausführbare Form. Build-Automatisierung umfasst:

  1. Herunterladen von Abhängigkeiten
  2. Kompilieren von Quellcode in Binärcode
  3. Paketieren dieses Binärcodes
  4. Ausführen von Tests
  5. Einführung in Produktionssysteme

Abhängigkeitsmanagement und Build-Tools in Java:

  • ANT + Ivy (2000/2004)
  • Maven (2004)
  • Gradle (2012)

Apache ANT (Another Neat Tool) ist ein Open-Source-Projekt von Apache, veröffentlicht im Jahr 2000. Es ist eine Java-Bibliothek, die für die Automatisierung der Build-Prozesse für Java-Anwendungen verwendet wird. Sie kann auch für die Erstellung von Nicht-Java-Anwendungen verwendet werden. Sie folgt dem Prinzip „Konfiguration vor Konvention“. In Ant werden die verschiedenen Phasen des Build-Prozesses als „Targets“ bezeichnet. ANT-Build-Dateien sind in XML geschrieben und werden üblicherweise als „build.xml“ bezeichnet. Sie enthält drei Elemente: Projekt, Ziel und Aufgabe. Jede Build-Datei enthält ein Projekt. Alles, was in der build.xml steht, befindet sich unter dem Element project. Das Projekt enthält mindestens ein Ziel (Standard). Das Ziel enthält eine Reihe von Aufgaben und definiert einen bestimmten Zustand des Build-Prozesses. Eine Aufgabe ist ein Stück Code, das ausgeführt werden kann. Jedem Knoten können Attribute zugeordnet sein:

Attribute von Project:

  • Name: Der Name des Projekts.
  • Basedir: Der Stammordner für das Projekt und ist optional.
  • Default: Das Standardziel für den Build. Das Projekt kann ein oder mehrere Ziele haben. Es wird verwendet, um das Standardziel des Projekts anzugeben.

Attribute des Ziels:

  • Name: Der Name des Ziels.
  • Beschreibung: Eine Beschreibung über das Ziel.
  • Depends: Liste aller Ziele, getrennt durch Komma, von denen dieses Ziel abhängt.
  • Wenn: Das Ziel wird ausgeführt, wenn das Attribut true ist.
  • Unless: Das Ziel wird ausgeführt, wenn das Attribut nicht gesetzt ist.

Build.xml Beispiel:

<?xml version="1.0"?>
<project>
<target name="hello">
<echo>Hello, World</echo>
</target>
</project>

Add dependency in Ant + Ivy:

<dependency org="org.projectlombok" name="lombok" rev="1.18.10"/>

Der Hauptvorteil von Ant ist seine Flexibilität. Ant zwingt dem Entwickler keine Codierungskonventionen oder Projektstruktur auf. Das bedeutet, dass Ant von den Entwicklern verlangt, alle Befehle selbst zu schreiben, was manchmal zu großen Build-Dateien führt und schwer zu pflegen ist. Ursprünglich hatte Ant keine integrierte Unterstützung für die Verwaltung von Abhängigkeiten. Später wurde Apache Ivy, das als Unterprojekt des Apache Ant-Projekts entwickelt wurde, für die Verwaltung von Abhängigkeiten übernommen.

Apache Maven

Es ist ein Tool zur Verwaltung von Abhängigkeiten und zur Automatisierung von Builds, das 2004 veröffentlicht wurde. Es verwendet weiterhin XML, überwindet aber die Nachteile, indem es dem Prinzip „Convention over configuration“ folgt. Es stützt sich auf Konventionen und bietet vordefinierte Befehle (Goals). Die Konfigurationsdatei, die Anweisungen zum Erstellen und Verwalten von Abhängigkeiten enthält, wird üblicherweise „pom.xml“ genannt und befindet sich im Stammordner des Projekts.

Maven-Workflow

Die Maven-Engine nimmt pom.xml und das Projekt als Eingaben. Sie liest die pom.xml-Datei und lädt die darin erwähnten Abhängigkeiten als jar-Dateien in das lokale Repository herunter. Dann führt sie die Lebenszyklen, Build-Phasen und Plugins aus. Am Ende wird ein gepacktes und getestetes Artefakt erzeugt.

pom.xml Beispiel:

Einige wichtige Tags in der pom.xml Datei:

  • groupId: Sie steht für die Organisation, zu der das Projekt gehört.
  • artifactId: Es ist der Name des Projekts.
  • version: Es stellt die Version des Projekts dar.
  • packaging: Es repräsentiert die endgültige Form des Builds des Projekts. z.B. jar, war.

Add dependency in maven:

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
</dependency>

Maven repository:

Ein Repository ist ein Verzeichnis, in dem alle verpackten jar-Dateien zusammen mit ihren eigenen pom-Dateien existieren. Diese pom-Dateien enthalten die externen Abhängigkeiten des jeweiligen Projekts. Auf diese Weise lädt maven die Abhängigkeiten Ihres Projekts rekursiv herunter, bis alle erforderlichen Abhängigkeiten in Ihrem lokalen Repository vorhanden sind. Es gibt drei Arten von Repositories in maven:

  1. Lokales Repository: Es ist ein Repository, das auf dem Rechner des Entwicklers selbst vorhanden ist.
  2. Organisationsebene/entferntes Repository: Es handelt sich um ein Repository, das innerhalb der Organisation vorhanden ist.
  3. Zentrales Repository: Es ist ein Repository im Internet, das von der Maven-Community erstellt und gepflegt wird.

Wenn eine Abhängigkeit in der pom.xml-Datei eines Projekts angegeben wird, sucht Maven danach im lokalen Repository. Wenn sie dort nicht gefunden wird, wird sie im entfernten/org-weiten Repository gesucht. Ist es auch dort nicht vorhanden, wird es im zentralen Repository gesucht.

Maven schreibt eine strenge Projektstruktur vor, während Ant auch hier Flexibilität bietet. Seine strengen Konventionen haben den Preis, dass es viel weniger flexibel ist als Ant – Zielanpassungen sind sehr schwierig.

Nachteile von Maven:

  1. Das Abhängigkeitsmanagement kann Konflikte zwischen verschiedenen Versionen derselben Bibliothek nicht gut handhaben.
  2. Die Anpassung von Zielen ist schwierig.

Gradle

Es ist ein Open-Source-Abhängigkeitsmanagement- und Build-Automatisierungswerkzeug, das 2012 veröffentlicht wurde. Es kombiniert die guten Teile von Apache Ant und Apache Maven und baut darauf auf und verwendet eine domänenspezifische Sprache (basierend auf Groovy) anstelle von XML. Es hat die Flexibilität von Ant und den Lebenszyklus von Maven übernommen. Außerdem folgt es dem Prinzip „Konvention vor Konfiguration“. Es unterstützt Maven- und Ivy-Repositories zum Auffinden der Abhängigkeiten. Seine Konfigurationsdatei wird konventionell als „build.gradle“ bezeichnet und befindet sich im Stammverzeichnis des Projekts. Gradle gab seinen Build-Schritten den Namen „Tasks“, im Gegensatz zu Ant’s „Targets“ oder Maven’s „Phases“. Google hat Gradle als Standard-Build-Tool für Android OS übernommen.

Gradle verwendet kein XML. Stattdessen hat es seine eigene domänenspezifische Sprache, die auf Groovy (eine der JVM-Sprachen) basiert. Infolgedessen sind Gradle-Build-Skripte in der Regel viel kürzer und übersichtlicher als diejenigen, die für Ant oder Maven geschrieben wurden. Der Umfang des Boilerplate-Codes ist mit Gradle viel geringer.

Gradle-Konfigurationen

  • Implementierung: Es wird verwendet, um Abhängigkeiten zu deklarieren, die wir nicht für die Kompilierzeit unserer Konsumenten offenlegen wollen.
  • api: Es wird verwendet, um Abhängigkeiten zu deklarieren, die Teil unserer API sind, d.h. für Abhängigkeiten, die wir explizit unseren Verbrauchern zugänglich machen wollen.
  • compileOnly: Hier können wir Abhängigkeiten deklarieren, die nur zur Kompilierzeit verfügbar sein sollen, aber zur Laufzeit nicht benötigt werden. Ein Beispiel für diese Konfiguration ist ein Annotationsprozessor wie Lombok, der den Bytecode zur Kompilierzeit modifiziert. Nach der Kompilierung wird er nicht mehr benötigt, also ist die Abhängigkeit zur Laufzeit nicht verfügbar.
  • runtimeOnly: Es erlaubt uns, Abhängigkeiten zu deklarieren, die zur Kompilierzeit nicht benötigt werden, aber zur Laufzeit verfügbar sein werden. Ein Beispiel ist SLF4J, wo wir slf4j-api in die implementation-Konfiguration und eine Implementierung dieser API (wie slf4j-log4j12 oder logback-classic) in die runtimeOnly-Konfiguration aufnehmen.
  • testImplementation: Ähnlich wie implementation, aber mit testImplementation deklarierte Abhängigkeiten sind nur während der Kompilierung und Laufzeit von Tests verfügbar. Wir können es verwenden, um Abhängigkeiten zu Test-Frameworks wie JUnit oder Mockito zu deklarieren, die wir nur in Tests benötigen und die im Produktionscode nicht verfügbar sein sollten.
  • testCompileOnly: Ähnlich wie compileOnly, aber mit testCompileOnly deklarierte Abhängigkeiten sind nur während der Kompilierung von Tests verfügbar und nicht zur Laufzeit.
  • testRuntimeOnly: Ähnlich wie runtimeOnly, aber mit testRuntimeOnly deklarierte Abhängigkeiten sind nur während der Laufzeit von Tests verfügbar und nicht zur Kompilierzeit.

Projekte und Aufgaben in Gradle

Jeder Gradle Build besteht aus einem oder mehreren Projekten. Jedes Projekt besteht aus einer Reihe von Aufgaben. Jede Aufgabe repräsentiert ein einzelnes Stück Arbeit, das ein Build durchführt, z.B. JavaDoc generieren, einige Archive in einem Repository veröffentlichen, usw.

build.gradle Beispiel

Gradle Repository:

Die „Aliase“ in Gradle werden verwendet, wenn wir Maven Repositories zu unserem Projekt-Build hinzufügen. Diese Aliase lauten wie folgt:

  • mavenCentral(): Dieser Alias steht für die Abhängigkeiten, die aus dem zentralen Maven 2 Repository geholt werden.
  • jcenter(): Dieser Alias steht für die Abhängigkeiten, die aus dem Bintray’s JCenter Maven Repository geholt werden.
  • mavenLocal(): Dieser Alias steht für die Abhängigkeiten, die aus dem lokalen Maven Repository geholt werden.

Beispiel: Fügen Sie das zentrale Maven Repository in unserem Projekt hinzu, fügen Sie den folgenden Codeschnipsel zu unserer ‚build.gradle‘ Datei hinzu:

repositories {
mavenCentral()
}

Add dependency in Gradle:

compile group: 'org.hibernate', name: 'hibernate-core', version: '3.6.7.Final'

Vorteile:

  1. Es behandelt transitive Abhängigkeiten ziemlich gut. Wenn eine kollidierende transitive Abhängigkeit im Projekt vorhanden ist, wählt es die neueste Version der Abhängigkeit, um sie aufzulösen. Zum Beispiel erfordert Abhängigkeit ‚A‘ intern Abhängigkeit ‚C‘ mit Version 2.0 und Abhängigkeit ‚B‘ erfordert intern Abhängigkeit ‚C‘ mit Version 3.0. Dann wird Gradle die neueste Version der Abhängigkeit ‚C‘ verwenden.
  2. Die Konfigurationsdateien von Gradle sind kleiner und sauberer, da es eine domänenspezifische Sprache verwendet, die auf Groovy anstelle von XML basiert.
  3. Gradle verwendet ein inkrementelles Build-Konzept und vermeidet Arbeit, indem es die Ein- und Ausgabe von Aufgaben verfolgt und nur das ausführt, was notwendig ist, und nur Dateien verarbeitet, die sich geändert haben, wenn dies möglich ist, und daher schneller als Maven arbeitet.

Schreibe einen Kommentar