Unterschiede zwischen dependencyManagement und Abhängigkeiten in Maven

766

Was ist der Unterschied zwischen dependencyManagementund dependencies? Ich habe die Dokumente auf der Apache Maven-Website gesehen. Es scheint, dass eine unter dem definierte Abhängigkeit dependencyManagementin den untergeordneten Modulen verwendet werden kann, ohne die Version anzugeben.

Zum Beispiel:

Ein übergeordnetes Projekt (Pro-par) definiert eine Abhängigkeit unter dependencyManagement:

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8</version>
    </dependency>
 </dependencies>
</dependencyManagement>

Dann kann ich im Kind von Pro-par das junit verwenden:

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
    </dependency>
 </dependencies>

Ich frage mich jedoch, ob es notwendig ist, junit im übergeordneten pom zu definieren. Warum nicht direkt im benötigten Modul definieren?

hguser
quelle

Antworten:

464

Mit dem Abhängigkeitsmanagement können Sie das Management von Abhängigkeitsversionen konsolidieren und zentralisieren, ohne Abhängigkeiten hinzuzufügen, die von allen untergeordneten Elementen geerbt werden. Dies ist besonders nützlich, wenn Sie über eine Reihe von Projekten (dh mehrere) verfügen , die ein gemeinsames übergeordnetes Element erben.

Ein weiterer äußerst wichtiger Anwendungsfall dependencyManagementist die Steuerung von Versionen von Artefakten, die in transitiven Abhängigkeiten verwendet werden. Dies ist ohne Beispiel schwer zu erklären. Zum Glück ist dies in der Dokumentation dargestellt.

Pascal Thivent
quelle
17
Ist es also notwendig, Abhängigkeiten in untergeordneten Projekt-POMs zu deklarieren, selbst wenn sie im übergeordneten Projekt-POM im Abschnitt <dependencyManagement> deklariert wurden? Ist es möglich, Abhängigkeiten zu vererben?
Johnny-B-Goode
55
Ja, Sie müssen sie noch im untergeordneten POM definieren, um zu zeigen, dass Sie sie verwenden. Sie sind nicht in den untergeordneten Projekten enthalten, nur weil sie <dependencyManagement>im übergeordneten POM enthalten sind. Durch das Einschließen von Abhängigkeiten in wird <dependencyManagement>die Verwaltung der Version, des Bereichs und der Ausschlüsse für jede Abhängigkeit zentralisiert, wenn Sie sich für die Verwendung entscheiden. Mavens Leitfaden zum Abhängigkeitsmanagement geht auf alle Details ein.
hotshot309
2
Der zweite Absatz ( dependencyManagementsteuert auch transitive Abhängigkeiten) ist nur wahr, wenn die Abhängigkeiten explizit festgelegt sind: stackoverflow.com/questions/28312975/…
Robert Metzger
2
@ johnny-b-goode Was Sie noch tun können, ist einen neuen dependenciesAbschnitt in Ihrem Eltern-Pom zu erstellen . Wir haben das so gemacht, dass alle untergeordneten Projekte standardmäßig einige Apache-Commons haben und diese nicht immer deklarieren.
Februar
771

Ich bin modisch spät dran bei dieser Frage, aber ich denke, es ist eine klarere Antwort wert als die akzeptierte (was richtig ist, aber nicht den eigentlichen wichtigen Teil betont, den Sie selbst ableiten müssen).

Im übergeordneten POM besteht der Hauptunterschied zwischen <dependencies>und <dependencyManagement>darin:

In diesem <dependencies>Abschnitt angegebene Artefakte werden IMMER als Abhängigkeit der untergeordneten Module aufgenommen.

Im <dependencyManagement>Abschnitt angegebene Artefakte werden nur dann in das untergeordnete Modul aufgenommen, wenn sie auch im <dependencies>Abschnitt des untergeordneten Moduls selbst angegeben wurden. Warum ist es gut, dass du fragst? weil Sie die Version und / oder den Bereich im übergeordneten Element angeben und diese beim Angeben der Abhängigkeiten im untergeordneten POM weglassen können. Dies kann Ihnen helfen, einheitliche Versionen für Abhängigkeiten für untergeordnete Module zu verwenden, ohne die Version in jedem untergeordneten Modul anzugeben.

dcoder
quelle
1
Aber ist es nicht auch ein bisschen Overhead, <dependencyManagement>Over <dependencies>in der Wurzel zu verwenden .pom? Kinder pomkönnten viel kürzer sein.
Janez Kuhar
18
Das stimmt. Wenn Sie <dependencies> anstelle von <dependencyManagement> verwenden, werden kürzere untergeordnete Poms erstellt. Dies ist jedoch mit Kosten verbunden. Dies bedeutet, dass diese Abhängigkeiten IMMER für ALLE untergeordneten Module definiert werden. Wenn nur EINIGE der untergeordneten Module eine bestimmte Abhängigkeit benötigen, können Sie bei Verwendung von "<dependencyManagement>" auswählen, welche untergeordneten Module diese Abhängigkeit aufweisen, und dennoch ein wenig effizient sein, indem Sie die Abhängigkeitsversion nur im übergeordneten POM festlegen.
dcoder
2
@JanezKuhar Es ist für mich sinnvoll, dass wenn Sie eine Abhängigkeit im untergeordneten Modul angeben, diese im übergeordneten Modul überschrieben wird, aber ich gebe zu, dass ich mich nicht erinnere. Ich muss die Maven-Dokumente auf diese überprüfen, wenn ich die Gelegenheit dazu bekomme. Obwohl es vielleicht einfacher ist, einfach ein einfaches Eltern-Kind-Projekt
einzurichten
26
Gute Erklärung für ein einfaches Konzept - warum fällt es Maven anscheinend so schwer, ihr eigenes Werkzeug so einfach zu erklären?
Jimmy_terra
1
Ich würde hinzufügen, Artifacts specified in the <dependencies> section will ALWAYS be included as a dependency of the child module(s)dass sie auch im Elternteil enthalten sind. Es scheint nicht möglich zu sein, eine Abhängigkeit für Kinder festzulegen, nicht jedoch für die Eltern.
Caduceus
54

Die Dokumentation auf der Maven-Site ist schrecklich. DependencyManagement verschiebt einfach Ihre Abhängigkeitsdefinitionen (Version, Ausschlüsse usw.) auf den übergeordneten POM. In den untergeordneten Poms müssen Sie lediglich die groupId und die Artefakt-ID eingeben. Das war's (mit Ausnahme der übergeordneten Pom-Verkettung und dergleichen, aber das ist auch nicht wirklich kompliziert - dependencyManagement gewinnt über Abhängigkeiten auf übergeordneter Ebene - aber wenn Sie eine Frage dazu haben oder importieren, ist die Maven-Dokumentation etwas besser).

Nachdem ich den gesamten Müll 'a', 'b', 'c' auf der Maven-Site gelesen und verwirrt war, schrieb ich ihr Beispiel neu. Wenn Sie also zwei Projekte (proj1 und proj2) hatten, die eine gemeinsame Abhängigkeit (betaShared) haben, können Sie diese Abhängigkeit auf das übergeordnete POM verschieben. Während Sie gerade dabei sind, können Sie auch andere Abhängigkeiten (Alpha und Charlie) nach oben verschieben, jedoch nur, wenn dies für Ihr Projekt sinnvoll ist. Für die in den vorherigen Sätzen beschriebene Situation ist hier die Lösung mit dependencyManagement im übergeordneten pom:

<!-- ParentProj pom -->
<project>
  <dependencyManagement>
    <dependencies>
      <dependency> <!-- not much benefit defining alpha here, as we only use in 1 child, so optional -->
        <groupId>alpha</groupId>
        <artifactId>alpha</artifactId>
        <version>1.0</version>
        <exclusions>
          <exclusion>
            <groupId>zebra</groupId>
            <artifactId>zebra</artifactId>
          </exclusion>
        </exclusions>
      </dependency>
      <dependency>
        <groupId>charlie</groupId> <!-- not much benefit defining charlie here, so optional -->
        <artifactId>charlie</artifactId>
        <version>1.0</version>
        <type>war</type>
        <scope>runtime</scope>
      </dependency>
      <dependency> <!-- defining betaShared here makes a lot of sense -->
        <groupId>betaShared</groupId>
        <artifactId>betaShared</artifactId>
        <version>1.0</version>
        <type>bar</type>
        <scope>runtime</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>
</project>

<!-- Child Proj1 pom -->
<project>
  <dependencies>
    <dependency>
      <groupId>alpha</groupId>
      <artifactId>alpha</artifactId>  <!-- jar type IS DEFAULT, so no need to specify in child projects -->
    </dependency>
    <dependency>
      <groupId>betaShared</groupId>
      <artifactId>betaShared</artifactId>
      <type>bar</type> <!-- This is not a jar dependency, so we must specify type. -->
    </dependency>
  </dependencies>
</project>

<!-- Child Proj2 -->
<project>
  <dependencies>
    <dependency>
      <groupId>charlie</groupId>
      <artifactId>charlie</artifactId>
      <type>war</type> <!-- This is not a jar dependency, so we must specify type. -->
    </dependency>
    <dependency>
      <groupId>betaShared</groupId> 
      <artifactId>betaShared</artifactId> 
      <type>bar</type> <!-- This is not a jar dependency, so we must specify type. -->
    </dependency>
  </dependencies>
</project>
MattC
quelle
2
Etwas abseits des Themas stehende Frage: Was bedeutet der Abhängigkeitstyp "Balken"? Ich habe in einem Beispiel Pom in der Maven-Dokumentation gesehen, konnte aber keine Definition finden. Ich nahm an, dass es ein Tippfehler von "Krieg" oder "Glas" war, aber ich sehe es in anderen Beispielen wie Ihrem.
NobodyMan
NobodyMan - Es ist also nur ein Platzhalter für einen anderen Archivtyp. Wie mit 'foo'. Oder es könnte verwendet werden, wenn jemand einen benutzerdefinierten Typ mit der Erweiterungsleiste 'bar' erstellt hat. Und es gibt viele obskure Archivtypen. Wie sar, das ist jboss service archive.
MattC
Ihr Beispiel ist ziemlich klar und bekräftigt, was ich selbst aus der Dokumentation herausgearbeitet habe. Haben Sie es beim Maven-Projekt eingereicht? Nachdem ich Ihr Beispiel studiert habe, bereite ich mich darauf vor, ein POM zu vereinfachen, das beides enthält und nur Abhängigkeitserklärungen benötigt, da das Projekt, mit dem es verknüpft ist, keine Kinder hat.
David A. Gray
Nun, ich wollte gerade den DependencyManagement-Knoten löschen, bis mir der Gedanke kam, dass ich durch Verlassen des Knotens eine Mindestversion für alle untergeordneten POMs festlegen kann, die indirekt in den Abhängigkeitsbaum gelangen. Als ich beispielsweise javax.cache.cache-apI verfolgte, entdeckte ich eine wesentlich neuere Version 1.0.0 (gegenüber 0.3.0), die ebenso gut überall verwendet werden kann.
David A. Gray
Diese Erklärung ist perfekt.
Smart Coder
45

Es ist wie du gesagt hast; dependencyManagementwird verwendet, um alle Abhängigkeitsinformationen in eine gemeinsame POM-Datei zu ziehen und die Verweise in der untergeordneten POM-Datei zu vereinfachen.

Dies ist nützlich, wenn Sie mehrere Attribute haben, die Sie unter mehreren untergeordneten Projekten nicht erneut eingeben möchten.

Schließlich dependencyManagementkann verwendet werden , um eine Standard - Version eines Artefakts zu definieren , über mehrere Projekte hinweg zu nutzen.

Pran
quelle
4
Abhängigkeiten werden also nicht vererbt? Muss es trotzdem im Pom des Kinderprojekts deklariert werden?
Johnny-B-Goode
6
Ja, Sie müssen sie trotzdem in untergeordneten Projekten deklarieren, ohne jedoch eine Version anzugeben.
Pavel Vlasov
Dieses Szenario ist nützlich, wenn Sie Versionen in mehreren Java-Projekten mit Eltern-Kind-Beziehung verwalten möchten.
Anuj Kumar
43

Es gibt immer noch eine Sache, die meiner Meinung nach nicht genug hervorgehoben wird, und das ist unerwünschte Vererbung .

Hier ist ein inkrementelles Beispiel:

Ich erkläre in meinem parentPom:

<dependencies>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>19.0</version>
        </dependency>
</dependencies>

Boom! Ich habe es in meiner Child A, Child Bund Child CModule:

  • Implizität von Kinderpoms geerbt
  • Ein einziger Ort zum Verwalten
  • Keine Notwendigkeit, irgendetwas in Kinderpoms neu zu deklarieren
  • Ich kann mich immer noch neu kümmern und version 18.0in einem überschreiben, Child Bwenn ich will.

Aber was ist, wenn ich am Ende keine Guave brauche Child Cund auch nicht in der Zukunft Child Dund in den Child EModulen?

Sie werden es immer noch erben und das ist unerwünscht! Dies ist genau wie der Geruch von Java God Object-Code, bei dem Sie einige nützliche Teile von einer Klasse und eine Menge unerwünschter Dinge erben.

Hier <dependencyManagement>kommt das Spiel ins Spiel. Wenn Sie dies zu Ihrem übergeordneten POM hinzufügen, hören alle Ihre untergeordneten Module auf , es zu sehen . Und so sind Sie gezwungen , in jedes einzelne Modul, das es benötigt, zu gehen und es erneut zu deklarieren ( Child Aund zwar Child Bohne die Version).

Und natürlich tun Sie es nicht dafür Child C, und somit bleibt Ihr Modul schlank.

Andrejs
quelle
Werden die in <dependencyManagement> genannten Abhängigkeiten für das übergeordnete POM-Projekt heruntergeladen?
Jaspreet Jolly
Sind Sie sicher, dass <dependencyManagement>Abhängigkeiten standardmäßig nicht an die untergeordneten Poms vererbt werden , wenn wir sie im übergeordneten POM verwenden? Denn im Dokument: maven.apache.org/guides/introduction/…<dependencyManagement> sieht es so aus, als würde es standardmäßig vererbt, während die zweite Verwendung des erklärt wird. In einer Zeile heißt es: "Wenn Maven in Projekt B ausgeführt wird, wird Version 1.0 der Artefakte a, b, c und d unabhängig von der in ihrem POM angegebenen Version verwendet, obwohl" b "in nicht verwendet wird das Projekt B
Chirag Soni
Probieren Sie es selbst aus
Andrejs
17

Es gibt einige Antworten, die Unterschiede zwischen <depedencies>und <dependencyManagement>Tags mit maven beschreiben.

Im Folgenden werden jedoch einige Punkte kurz zusammengefasst:

  1. <dependencyManagement>Ermöglicht die Konsolidierung aller Abhängigkeiten (die auf untergeordneter Ebene verwendet werden), die in verschiedenen Modulen verwendet werden - Klarheit , zentrale Verwaltung der Abhängigkeitsversionen
  2. <dependencyManagement>ermöglicht das einfache Aktualisieren / Herabstufen von Abhängigkeiten je nach Bedarf. In anderen Szenarien muss dies auf jeder untergeordneten POM-Ebene ausgeübt werden - Konsistenz
  3. Die im <dependencies>Tag angegebenen Abhängigkeiten werden immer importiert, während die <dependencyManagement>im übergeordneten POM angegebenen Abhängigkeiten nur importiert werden, wenn der untergeordnete POM einen entsprechenden Eintrag in seinem <dependencies>Tag hat.
Amit Kaneria
quelle
17

Entschuldigung, ich bin sehr spät zur Party.

Lassen Sie mich versuchen, den Unterschied mit dem mvn dependency:treeBefehl zu erklären

Betrachten Sie das folgende Beispiel

Übergeordnetes POM - Mein Projekt

<modules>
    <module>app</module>
    <module>data</module>
</modules>

<dependencies>
    <dependency>
        <groupId>com.google.guava</groupId>
        <artifactId>guava</artifactId>
        <version>19.0</version>
    </dependency>
</dependencies>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.9</version>
        </dependency>
    </dependencies>
</dependencyManagement>

Untergeordnetes POM - Datenmodul

<dependencies>
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
    </dependency>
</dependencies>

Untergeordnetes POM - App-Modul (hat keine zusätzliche Abhängigkeit, lässt also die Abhängigkeiten leer)

 <dependencies>
</dependencies>

Beim Ausführen des mvn dependency:treeBefehls erhalten wir folgendes Ergebnis

Scanning for projects...
------------------------------------------------------------------------
Reactor Build Order:

MyProject
app
data

------------------------------------------------------------------------
Building MyProject 1.0-SNAPSHOT
------------------------------------------------------------------------

--- maven-dependency-plugin:2.8:tree (default-cli) @ MyProject ---
com.iamvickyav:MyProject:pom:1.0-SNAPSHOT
\- com.google.guava:guava:jar:19.0:compile

------------------------------------------------------------------------
Building app 1.0-SNAPSHOT
------------------------------------------------------------------------

--- maven-dependency-plugin:2.8:tree (default-cli) @ app ---
com.iamvickyav:app:jar:1.0-SNAPSHOT
\- com.google.guava:guava:jar:19.0:compile

------------------------------------------------------------------------
Building data 1.0-SNAPSHOT
------------------------------------------------------------------------

--- maven-dependency-plugin:2.8:tree (default-cli) @ data ---
com.iamvickyav:data:jar:1.0-SNAPSHOT
+- org.apache.commons:commons-lang3:jar:3.9:compile
\- com.google.guava:guava:jar:19.0:compile

Google Guave wird in jedem Modul (einschließlich des übergeordneten Moduls) als Abhängigkeit aufgeführt , während das Apache Commons nur im Datenmodul (nicht einmal im übergeordneten Modul) als Abhängigkeit aufgeführt wird.

IamVickyAV
quelle
11

Wenn die Abhängigkeit im dependencyManagement-Element des Poms der obersten Ebene definiert wurde, musste das untergeordnete Projekt die Version der Abhängigkeit nicht explizit auflisten. Wenn das untergeordnete Projekt eine Version definiert, wird die im Abschnitt dependencyManagement der obersten Ebene des POM aufgeführte Version überschrieben. Das heißt, die dependencyManagement-Version wird nur verwendet, wenn das Kind eine Version nicht direkt deklariert.

Mustafa Güven
quelle
1
Ich glaube, diese Aussage ist möglicherweise nicht richtig. In den Beispielen für das Abhängigkeitsmanagement von Maven (Nr. 2) heißt es, dass Abhängigkeiten, die in einem übergeordneten POM mit einer Version definiert sind, die im untergeordneten POM angegebene Version überschreiben: "Wenn Maven in Projekt B Version 1.0 der Artefakte a, b, c ausgeführt wird , und d werden unabhängig von der in ihrem POM angegebenen Version verwendet. "
Devdanke
@devdanke Mindestens Eclipse M2e gibt eine Warnung aus : Version verwalten überwiegende ... für ... .
GeroldBroser setzt Monica
4

Im übergeordneten POM besteht der Hauptunterschied zwischen <dependencies>und <dependencyManagement>darin:

In diesem <dependencies>Abschnitt angegebene Artefakte werden IMMER als Abhängigkeit der untergeordneten Module aufgenommen.

Im Abschnitt angegebene Artefakte werden nur dann in das untergeordnete Modul aufgenommen, wenn sie auch im Abschnitt des untergeordneten Moduls selbst angegeben wurden. Warum ist es gut, dass du fragst? weil Sie die Version und / oder den Bereich im übergeordneten Element angeben und diese beim Angeben der Abhängigkeiten im untergeordneten POM weglassen können. Dies kann Ihnen helfen, einheitliche Versionen für Abhängigkeiten für untergeordnete Module zu verwenden, ohne die Version in jedem untergeordneten Modul anzugeben.

Ja
quelle
4

Nur in meinen eigenen Worten, Sie parent-projecthelfen Ihnen, zwei Arten von Abhängigkeiten bereitzustellen:

  • implizite Abhängigkeiten : Alle <dependencies>in Ihrem Abschnitt definierten Abhängigkeiten parent-projectwerden von allen geerbtchild-projects
  • explizite Abhängigkeiten : Mit dieser Option können Sie auswählen, welche Abhängigkeiten in Ihrem System angewendet werden sollen child-projects. Daher verwenden Sie den <dependencyManagement>Abschnitt, um alle Abhängigkeiten zu deklarieren, die Sie in Ihren verschiedenen verwenden werden child-projects. Das Wichtigste ist, dass Sie in diesem Abschnitt ein definieren, <version>damit Sie es in Ihrem nicht erneut deklarieren müssen child-project.

Das ist <dependencyManagement>aus meiner Sicht (korrigieren Sie mich, wenn ich falsch liege) nur nützlich, indem Sie die Version Ihrer Abhängigkeiten zentralisieren. Es ist wie eine Art Hilfsfunktion.

Harry Coder
quelle
1

In Eclipse gibt es eine weitere Funktion in der dependencyManagement. Wenn dependencieses ohne verwendet wird, werden die nicht gefundenen Abhängigkeiten in der POM-Datei bemerkt. Wenn dependencyManagementes verwendet wird, bleiben die ungelösten Abhängigkeiten in der POM-Datei unbemerkt und Fehler erscheinen nur in den Java-Dateien. (Importe und so ...)

Gangnus
quelle
1

Der Unterschied zwischen den beiden lässt sich am besten an einer scheinbar notwendigen und ausreichenden Definition des in den Maven-Website-Dokumenten verfügbaren dependencyManagement-Elements erkennen:

dependencyManagement

"Standardabhängigkeitsinformationen für Projekte, die von diesem erben. Die Abhängigkeiten in diesem Abschnitt werden nicht sofort aufgelöst. Wenn stattdessen ein von diesem abgeleiteter POM eine Abhängigkeit deklariert, die durch eine übereinstimmende Gruppen-ID und Artefakt-ID beschrieben wird, werden die Version und andere Werte aus diesem Abschnitt werden für diese Abhängigkeit verwendet, wenn sie nicht bereits angegeben wurden. " [ https://maven.apache.org/ref/3.6.1/maven-model/maven.html ]

Es sollte zusammen mit einigen weiteren Informationen auf einer anderen Seite gelesen werden:

„..Der minimale Satz von Informationen zum Abgleichen einer Abhängigkeitsreferenz mit einem dependencyManagement-Abschnitt ist tatsächlich {groupId, artefaktId, type, classifier}. In vielen Fällen beziehen sich diese Abhängigkeiten auf JAR-Artefakte ohne Klassifizierer. Auf diese Weise können wir die auf {groupId, artefaktId} festgelegte Identität kurz fassen, da der Standardwert für das Typfeld jar und der Standardklassifizierer null ist. “ [ https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html ]

Somit sind alle Unterelemente (Bereich, Ausschlüsse usw.) eines Abhängigkeitselements - außer groupId, artefaktId, Typ, Klassifizierer, nicht nur Version - zum Zeitpunkt der Sperrung / Standardeinstellung verfügbar (und werden somit von geerbt) dort weiter) geben Sie die Abhängigkeit innerhalb eines dependencyElement an. Wenn Sie eine Abhängigkeit mit den Unterelementen type und classifier (siehe die zuerst zitierte Webseite, um alle Unterelemente zu überprüfen) als nicht jar bzw. nicht null angegeben haben, benötigen Sie {groupId, artefaktId, classifier, type} Verweisen (Auflösen) dieser Abhängigkeit an einem beliebigen Punkt in einer Vererbung, die vom dependencyManagement-Element stammt. Andernfalls würde {groupId, artefaktId} ausreichen, wenn Sie nicht beabsichtigen, die Standardeinstellungen für Klassifizierer und Typ (jar bzw. null) zu überschreiben. Standard ist also ein gutes Schlüsselwort in dieser Definition. beliebige Unterelemente (außer groupId,

Daher wird jedes Abhängigkeitselement außerhalb von dependencyManagement, sei es als Verweis auf ein dependencyManagement-Element oder als eigenständiges Element, sofort aufgelöst (dh im lokalen Repository installiert und für Klassenpfade verfügbar).

rps
quelle