web-dev-qa-db-fra.com

Différences entre dependencyManagement et dépendances dans Maven

Quelle est la différence entre dependencyManagement et dependencies? J'ai vu la documentation sur le site Web d'Apache Maven. Il semble qu'une dépendance définie sous dependencyManagement puisse être utilisée dans ses modules enfants sans spécifier la version.

Par exemple:

Un projet parent (Pro-par) définit une dépendance sous dependencyManagement:

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

Ensuite, dans l’enfant de Pro-par, je peux utiliser le junit:

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

Cependant, je me demande s'il est nécessaire de définir Junit dans le pom parent? Pourquoi ne pas le définir directement dans le module souhaité?

648
hguser

Dependency Management permet de consolider et de centraliser la gestion des versions de dépendance sans ajouter de dépendances héritées par tous les enfants. Ceci est particulièrement utile lorsque vous avez un ensemble de projets (c'est-à-dire plusieurs) qui héritent d'un parent commun.

Un autre cas d'utilisation extrêmement important de dependencyManagement est le contrôle des versions d'artefacts utilisées dans les dépendances transitives. C'est difficile à expliquer sans exemple. Heureusement, cela est illustré dans la documentation.

414
Pascal Thivent

Je suis à la mode avec un peu de retard par rapport à cette question, mais je pense qu’elle mérite une réponse plus claire que celle acceptée (ce qui est correct, mais ne met pas l’accent sur la partie réellement importante, que vous devez déduire vous-même).

Dans le POM parent, la principale différence entre <dependencies> et <dependencyManagement> est la suivante:

Les artefacts spécifiés dans la section <dependencies> seront TOUJOURS inclus en tant que dépendance du (des) module (s) enfant (s).

Les artefacts spécifiés dans la section <dependencyManagement> ne seront inclus dans le module enfant que s'ils ont également été spécifiés dans la section <dependencies> du module enfant. lui-même. Pourquoi est-ce bien que tu demandes? parce que vous spécifiez la version et/ou la portée dans le parent et que vous pouvez les omettre lors de la spécification des dépendances dans le POM enfant. Cela peut vous aider à utiliser des versions unifiées pour les dépendances des modules enfants sans spécifier la version dans chaque module enfant.

635
dcoder

Le documentation sur le site Maven est horrible. DependencyManagement ne fait que déplacer vos définitions de dépendance (version, exclusions, etc.) vers le pom parent, puis, dans les poms enfants, il vous suffit de mettre groupId et artifactId. C'est tout (sauf pour le pom chaining parent, etc., mais ce n'est pas vraiment compliqué non plus - dependencyManagement l'emporte sur les dépendances au niveau parent - mais si vous avez une question à ce sujet ou importez, la documentation Maven est un peu meilleure).

Après avoir lu toutes les ordures 'a', 'b', 'c' sur le site Maven et m'être confus, j'ai réécrit leur exemple. Ainsi, si vous avez 2 projets (proj1 et proj2) qui partagent une dépendance commune (betaShared), vous pouvez déplacer cette dépendance vers le pom parent. Pendant que vous y êtes, vous pouvez également déplacer toutes les autres dépendances (alpha et charlie), mais uniquement si cela convient à votre projet. Donc, pour la situation décrite dans les phrases précédentes, voici la solution avec dependencyManagement dans le parent 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>
45
MattC

C'est comme tu l'as dit; dependencyManagementest utilisé pour extraire toutes les informations de dépendance dans un fichier POM commun, simplifiant ainsi les références dans le fichier POM enfant.

Cela devient utile lorsque vous avez plusieurs attributs que vous ne voulez pas retaper sous plusieurs projets enfants.

Enfin, dependencyManagement peut être utilisé pour définir une version standard d'un artefact à utiliser dans plusieurs projets.

44
Pran

Il y a encore une chose qui n'est pas assez soulignée, à mon avis, et qui est l'héritage non désiré .

Voici un exemple incrémental:

Je déclare dans mon parent pom:

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

boom! Je l'ai dans mes modules Child A, Child B et Child C:

  • Implication héritée des enfants poms
  • Un lieu unique à gérer
  • Pas besoin de redéclarer quoi que ce soit dans poms enfant
  • Je peux toujours redelcare et passer à version 18.0 dans un Child B si je le souhaite.

Mais que se passe-t-il si je n'ai pas besoin de goyave dans les modules Child C, ni dans le futur Child D et Child E?

Ils en hériteront quand même et c'est indésirable! C'est comme Java Odeur odeur de code objet, où vous héritez de quelques bits utiles d'une classe, et une tonne de choses indésirables aussi.

C'est ici que <dependencyManagement> entre en jeu. Lorsque vous ajoutez ceci à votre pom parent, tous vos modules enfants ARRÊTENT de le voir . Et ainsi vous êtes obligé d’entrer dans chaque module qui en a besoin et de le déclarer à nouveau (Child A et Child B, sans la version cependant).

Et, évidemment, vous ne le faites pas pour Child C, et votre module reste donc maigre.

33
Andrejs

Quelques réponses soulignent les différences entre les balises <depedencies> et <dependencyManagement> avec maven.

Cependant, quelques points sont expliqués ci-dessous de manière concise:

  1. <dependencyManagement> permet de consolider toutes les dépendances (utilisées au niveau du pom enfant) utilisées dans différents modules - clarté, gestion centrale des versions de dépendance
  2. <dependencyManagement> permet de mettre à niveau/rétrograder facilement les dépendances en fonction des besoins. Dans un autre scénario, cela doit être exercé à chaque niveau de pom enfant - cohérence
  3. les dépendances fournies dans la balise <dependencies> sont toujours importées, tandis que les dépendances fournies dans <dependencyManagement> dans le nom de famille pom ne seront importées que si l'enfant pom a une entrée respective dans sa balise <dependencies>.
15
Anamika

Si la dépendance était définie dans l'élément dependencyManagement du pom de niveau supérieur, il n'était pas nécessaire que le projet enfant répertorie explicitement la version de la dépendance. si le projet enfant définissait une version, il se substituerait à la version répertoriée dans la section dependencyManagement du POM de niveau supérieur. Autrement dit, la version de dependencyManagement n'est utilisée que lorsque l'enfant ne déclare pas une version directement.

9
Mustafa Güven

Désolé je suis très en retard à la fête.

Laissez-moi essayer d’expliquer la différence en utilisant la commande mvn dependency:tree

Considérons l'exemple ci-dessous

Parent POM - Mon projet

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

Child POM - module de données

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

Child POM - module d'application (n'a pas de dépendance supplémentaire, laissant ainsi des dépendances vides)

 <dependencies>
</dependencies>

En exécutant la commande mvn dependency:tree, nous obtenons le résultat suivant

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 guava est répertorié en tant que dépendance dans chaque module (y compris le parent), alors que Apache commons est répertorié en tant que dépendance uniquement dans le module de données (même dans le module parent)

6
IamVickyAV

Dans le POM parent, la principale différence entre le <dependencies> et le <dependencyManagement> est la suivante:

Les artefacts spécifiés dans la section <dependencies> seront toujours inclus en tant que dépendance du (des) module (s) enfant (s).

Les artefacts spécifiés dans la section ne seront inclus dans le module enfant que s'ils ont également été spécifiés dans la section du module enfant lui-même. Pourquoi est-ce bien que tu demandes? parce que vous spécifiez la version et/ou la portée dans le parent et que vous pouvez les omettre lors de la spécification des dépendances dans le POM enfant. Cela peut vous aider à utiliser des versions unifiées pour les dépendances des modules enfants sans spécifier la version dans chaque module enfant.

3
Yaver

La différence entre les deux est le mieux introduite dans ce qui semble une définition nécessaire et suffisante de l'élément dependencyManagement disponible dans la documentation du site Web Maven:

dependencyManagement

"Informations de dépendance par défaut pour les projets hérités de celui-ci. Les dépendances de cette section ne sont pas résolues immédiatement. Au lieu de cela, quand un POM dérivé de celui-ci déclare une dépendance décrite par un groupId et un artifactId correspondants, la version et les autres valeurs de cette section sont utilisés pour cette dépendance s'ils n'étaient pas déjà spécifiés. " [ https://maven.Apache.org/ref/3.6.1/maven-model/maven.html ]

Il devrait être lu avec quelques informations supplémentaires disponibles sur une autre page:

“..Le jeu minimal d'informations permettant de faire correspondre une référence de dépendance à une section dependencyManagement est en réalité {groupId, artifactId, type, classifieur}. Dans de nombreux cas, ces dépendances feront référence à des artefacts JAR sans classificateur. Cela nous permet de raccourcir le jeu d’identités en {groupId, artifactId}, car la valeur par défaut pour le champ type est jar et que le classificateur par défaut est null. ”[ https://maven.Apache.org/guides/ introduction/introduction-to-dependency-mécanisme.html ]

Ainsi, tous les sous-éléments (portée, exclusions, etc.) d’un élément de dépendance - autres que groupId, artifactId, type, classifieur, et pas seulement la version - sont disponibles pour le verrouillage/le défaut au point (et sont donc hérités de à partir de là) vous spécifiez la dépendance dans un dependencyElement. Si vous aviez spécifié une dépendance avec les sous-éléments type et classifier (voir la page Web citée en premier lieu pour vérifier tous les sous-éléments) comme étant non jar et non null, vous auriez besoin de {groupId, artifactId, classifieur, type} référencer (résoudre) cette dépendance en tout point d'un héritage provenant de l'élément dependencyManagement. Sinon, {groupId, artifactId} suffirait si vous ne souhaitez pas remplacer les valeurs par défaut du classificateur et du type (jar et null, respectivement). Donc, défaut est un bon mot clé dans cette définition; tout sous-élément (autre que groupId, artifactId, classifieur et type, bien sûr) explicitement affecté à une ou des valeurs au point auquel vous faites référence à une dépendance remplace les valeurs par défaut de l'élément dependencyManagement.

Ainsi, tout élément de dépendance en dehors de dependencyManagement, que ce soit en tant que référence à un élément dependencyManagement ou en tant qu’agent autonome, est immédiatement résolu (c’est-à-dire installé dans le référentiel local et disponible pour les chemins de classe).

1
rps

Dans Eclipse, il existe une fonctionnalité supplémentaire dans la variable dependencyManagement. Lorsque dependencies est utilisé sans cela, les dépendances non trouvées sont notées dans le fichier pom. Si vous utilisez dependencyManagement, les dépendances non résolues restent inaperçues dans le fichier pom et les erreurs n'apparaissent que dans les fichiers Java. (importations et autres ...)

1
Gangnus