DependencyManagementとMavenの依存関係の違い


766

違いは何であるdependencyManagementとはdependencies?Apache MavenのWebサイトでドキュメントを確認しました。で定義された依存関係dependencyManagementは、バージョンを指定せずに子モジュールで使用できるようです。

例えば:

親プロジェクト(Pro-par)は、以下の依存関係を定義しますdependencyManagement

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

次に、Pro-parの子で、junitを使用できます。

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

しかし、親pomでjunitを定義する必要があるのでしょうか。必要なモジュールで直接定義しないのはなぜですか?

回答:


464

依存関係管理を使用すると、すべての子に継承される依存関係を追加することなく、依存関係バージョンの管理を統合および一元化できます。これは、共通の親を継承するプロジェクトのセット(つまり、複数)がある場合に特に便利です。

のもう1つの非常に重要な使用例dependencyManagementは、推移的な依存関係で使用されるアーティファクトのバージョンの制御です。これは例なしでは説明するのが難しいです。幸いなことに、これはドキュメントに示されています。


17
それで、たとえ親プロジェクトのpomで<dependencyManagement>セクションで宣言されている場合でも、子プロジェクトのpomで依存関係を宣言する必要がありますか?依存関係を継承することは可能ですか?
johnny-b-goode 2012

55
はい、まだそれらを使用していることを示すために、子POMでそれらを定義する必要があります。<dependencyManagement>親POM に含まれているからといって、実際には子プロジェクトに含まれていません。依存関係をで囲む<dependencyManagement>と、バージョン、スコープ、および各依存関係の除外を集中的に管理できます。依存関係管理に関する Mavenのガイドでは、すべての詳細について説明しています。
hotshot309 2012

2
2番目の段落は(dependencyManagement依存関係を明示的に設定されている場合も、推移的依存関係を制御します)のみ真である:stackoverflow.com/questions/28312975/...
ロバート・メッツガー

2
@ johnny-b-goodeまだできるのdependenciesは、親のpomに新しいセクションを作成することです。すべての子プロジェクトにデフォルトでいくつかのapache-commonがあり、常にそれらを宣言しないようにするためです。
2006年

771

私はこの質問におしゃれに遅れていますが、受け入れられたものよりも明確な応答の価値があると思います(これは正しいですが、実際に重要な部分を強調していないため、推測する必要があります)。

親POMでは、との主な違い<dependencies>とは<dependencyManagement>これです:

<dependencies>セクションで指定されたアーティファクトは、常に子モジュールの依存関係として含まれます。

<dependencyManagement>セクションで指定されたアーティファクト<dependencies>は、子モジュール自体のセクションでも指定されている場合にのみ子モジュールに含まれます。なんでいいの?親でバージョンやスコープを指定し、子POMで依存関係を指定するときに省略できるためです。これにより、各子モジュールでバージョンを指定しなくても、子モジュールの依存関係に統一バージョンを使用できます。


1
しかし、ルートで<dependencyManagement>over <dependencies>を使用することは、少しのオーバーヘッドでもありません.pomか?子pomの方がはるかに短い可能性があります。
Janez Kuhar

18
それは本当だ。<dependencyManagement>の代わりに<dependencies>を使用すると、より短い子pomが作成されます。ただし、それにはコストが伴います。つまり、これらの依存関係は常にすべての子モジュールに対して定義されます。いくつかの子モジュールだけが特定の依存関係を必要とする場合は、代わりに "<dependencyManagement>"を使用すると、その依存関係を持つ子モジュールを選択でき、親pomでのみ依存関係バージョンを設定することで少し効率的です。
エンコーダー

2
@JanezKuhar子モジュールで依存関係を指定すると、親の依存関係がオーバーライドされることは理にかなっていますが、覚えていません。機会があったら、Mavenのドキュメントでそのドキュメントを確認する必要があります。単純な親子プロジェクトをセットアップして確認するだけの方が簡単かもしれませんが:)
dcoder

26
シンプルなコンセプトの良い説明-なぜMavenが自分のツールをこれほど簡単に説明するのがそれほど難しいように見えるのですか?
jimmy_terra 2017年

1
加えてArtifacts specified in the <dependencies> section will ALWAYS be included as a dependency of the child module(s)、それらは親にも含まれています。子には依存関係を設定できませんが、親には依存関係を設定できません。
カドゥケウス

54

Mavenサイトのドキュメントは恐ろしいものです。dependencyManagementが行うことは、依存関係の定義(バージョン、除外など)を親pomに移動するだけで、子pomにgroupIdとArtifactIdを配置するだけです。それだけです(親のpomチェーニングなどを除いて、それも実際には複雑ではありません。dependencyManagementは、親レベルの依存関係よりも優れています。しかし、それやインポートについて質問がある場合は、Mavenのドキュメントが少し優れています)。

Mavenサイトの「a」、「b」、「c」のすべてのゴミを読んで混乱した後、私はそれらの例を書き直しました。したがって、共通の依存関係(betaShared)を共有する2つのプロジェクト(proj1とproj2)がある場合、その依存関係を親pomに移動できます。その間、他の依存関係(アルファとチャーリー)を上に移動することもできますが、それがプロジェクトにとって意味のある場合に限られます。したがって、前の文で概説されている状況について、親pomにdependencyManagementを使用したソリューションを次に示します。

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

2
やや話題から外れた質問:依存関係の種類 "bar"は何を意味しますか?Mavenドキュメントのサンプルpomで見ましたが、定義が見つかりませんでした。「戦争」や「jar」のタイプミスだと思いましたが、あなたのような他の例でも見かけます。
NobodyMan、2016年

NobodyMan-したがって、これは別の種類のアーカイブのプレースホルダーにすぎません。'foo'を使うのと同じです。または、誰かが拡張子「bar」でカスタムタイプを作成した場合に使用できます。そして、そこにはあいまいなアーカイブの種類がたくさんあります。jbossサービスアーカイブであるsarのように。
MattC、2016年

あなたの例は非常に明確であり、ドキュメントから私が自分で作り出したものを再確認します。Mavenプロジェクトに提出しましたか?あなたの例を研究したので、関連付けられているプロジェクトには子がないため、両方を持ち、依存関係の宣言のみが必要なPOMを簡略化する準備をしています。
デビッドA.グレイ

まあ、DependencyManagementノードを削除しようとしていましたが、ノードを残しておくと、依存関係ツリーに間接的に移動する子POMの最小バージョンを確立できることがわかりました。例として、javax.cache.cache-apIを追跡して、ずっと新しいバージョン1.0.0(0.3.0ではない)を発見しました。
デビッドA.グレイ

この説明は完璧です。
スマートコーダー

45

それはあなたが言ったようなものです。dependencyManagementすべての依存関係情報を共通のPOMファイルに取り込むために使用され、子POMファイル内の参照を簡素化します。

複数の子プロジェクトで再入力したくない複数の属性がある場合に役立ちます。

最後に、dependencyManagement複数のプロジェクトで使用するアーティファクトの標準バージョンを定義するために使用できます。


4
だから、依存関係は継承されませんか?とにかく、子プロジェクトのpomで宣言する必要がありますか?
johnny-b-goode 2012

6
はい、とにかく子プロジェクトでそれらを宣言する必要がありますが、バージョンを指定する必要はありません。
Pavel Vlasov、2016年

このシナリオは、親子関係を持つ複数のJavaプロジェクトのバージョンを管理する場合に役立ちます。
Anuj Kumar

43

私の意見では、まだ十分に強調されていないことが1つあります。それは、不要な継承です。

これは増分の例です:

私は私のparentポンで宣言します:

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

ブーム!私は自分でそれを持っているChild AChild BChild Cモジュール:

  • 子どものポンポンが受け継いだ暗黙性
  • 管理する単一の場所
  • 子ポンで何も再宣言する必要はありません
  • 私はまだredelcareとオーバーライドすることができますversion 18.0Child B私がしたい場合。

しかし、もし私がChild C、そして将来Child DChild Eモジュールでもグアバを必要としない場合はどうなりますか?

彼らはまだそれを継承し、これは望ましくありません! これは、Java God Objectコードのにおいのようなもので、クラスからいくつかの有用なビットを継承し、大量の不要なものも同様に継承します。

これが<dependencyManagement>出番です。これを親pomに追加すると、すべての子モジュールがそれを表示しなくなります。そしてそれゆえ、あなたはそれを必要とする個々のモジュールに行き、それを再び宣言することを余儀なくされます(Child AそしてChild B、バージョンなしでも)。

そして、明らかに、あなたはのためChild Cにそれをしないので、あなたのモジュールは無駄のないままです。


<dependencyManagement>で言及されている依存関係は、親pomプロジェクトにダウンロードされますか?
Jaspreet Jolly

<dependencyManagement>親pomで使用する場合、デフォルトでは依存関係が子pomで継承されないことを確信していますか?なぜなら、doc:maven.apache.org/guides/introduction/…の2番目の使用を説明している間<dependencyManagement>、デフォルトで継承されるように見えるからです。「mavenがプロジェクトBで実行されると、pomで指定されたバージョンに関係なく、アーティファクトa、b、c、およびdのバージョン1.0が使用されます」で「b」が使用されていなくても、プロジェクトB
chirag soni


17

とmavenのタグの違いを概説するいくつかの回答が<depedencies>あり<dependencyManagement>ます。

ただし、簡潔な方法で以下に説明するいくつかのポイント:

  1. <dependencyManagement>異なるモジュール間で使用されるすべての依存関係(子pomレベルで使用される)を統合できます- 明確中央の依存関係バージョン管理
  2. <dependencyManagement>必要に応じて依存関係を簡単にアップグレード/ダウングレードできます。他のシナリオでは、これをすべての子pomレベルで実行する必要があります- 一貫性
  3. <dependencies>タグで提供される依存関係は常にインポートされますが<dependencyManagement>、親pomで提供される依存関係は、子pomの<dependencies>タグにそれぞれのエントリがある場合にのみインポートされます。

17

すみません、パーティーにはとても遅れています。

違いを説明してみましょう mvn dependency:treeコマンド

以下の例を考えてみましょう

親POM-マイプロジェクト

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

子POM-データモジュール

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

子POM-アプリモジュール(追加の依存関係がないため、依存関係は空のままにします)

 <dependencies>
</dependencies>

mvn dependency:treeコマンドを実行すると、次の結果が得られます

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グアバは、すべてのモジュール(親を含む)で依存関係としてリストされていますが、Apache Commonsは、データモジュール(親モジュールでさえも)でのみ依存関係としてリストされています


11

依存関係が最上位のpomのdependencyManagement要素で定義されている場合、子プロジェクトは依存関係のバージョンを明示的にリストする必要はありませんでした。子プロジェクトがバージョンを定義した場合は、最上位のPOMのdependencyManagementセクションにリストされているバージョンをオーバーライドします。つまり、dependencyManagementバージョンは、子がバージョンを直接宣言しない場合にのみ使用されます。


1
この発言は正しくないと思います。Mavenの依存関係管理の例(#2)では、親pomで定義された依存関係がバージョンで子pomで指定されたバージョンをオーバーライドすると言います。 、およびdは、pomで指定されたバージョンに関係なく使用されます。」
devdanke 2015

@devdanke少なくとも、Eclipse m2eは次の警告を発行します
GeroldBroserがモニカを2016

4

親POMでは、主な違い <dependencies><dependencyManagement>これです:

で指定されたアーティファクト <dependencies>セクションでモジュールの依存関係として含まれます。

セクションで指定されたアーティファクトは、子モジュール自体のセクションでも指定されている場合にのみ子モジュールに含まれます。なんでいいの?親でバージョンやスコープを指定し、子POMで依存関係を指定するときに省略できるためです。これにより、各子モジュールでバージョンを指定しなくても、子モジュールの依存関係に統一バージョンを使用できます。


4

私の言葉で言えば、あなたparent-projectはあなたが2種類の依存関係を提供するのを助けます:

  • 暗黙的な依存関係:の<dependencies>セクションで定義されているすべての依存関係は、すべての依存関係にparent-project継承されますchild-projects
  • 明示的な依存関係:に適用する依存関係を選択できますchild-projects。したがって、<dependencyManagement>セクションを使用して、別ので使用するすべての依存関係を宣言しますchild-projects。最も重要なことは、このセクションでを定義して、<version>で再度宣言する必要がないようにすることchild-projectです。

<dependencyManagement>あなたの依存関係のバージョンを集中支援することにより、単に便利である私の視点では、(私が間違っているなら、私を修正します)。ヘルパー機能のようなものです。


1

Eclipseでは、にもう1つの機能がありdependencyManagementます。ときにdependenciesそれなしで使用され、unfound依存関係がポンポンファイルに気づいています。場合dependencyManagementに使用され、未解決の依存関係がポンポンファイルとエラーに気付かれないまま、Javaファイルにのみ表示されます。(輸入など...)


1

2つの違いは、Maven Webサイトのドキュメントで利用できるdependencyManagement要素の必要かつ十分な定義にあるものが最も適切です。

dependencyManagement

「このプロジェクトから継承するプロジェクトのデフォルトの依存関係情報。このセクションの依存関係はすぐには解決されません。代わりに、このプロジェクトから派生したPOMが、一致するgroupIdとArtifactId、このセクションのバージョンとその他の値によって記述される依存関係を宣言すると、それらがまだ指定されていない場合は、その依存関係に使用されます。」[ https://maven.apache.org/ref/3.6.1/maven-model/maven.html ]

別のページで入手できるいくつかの詳細情報と一緒に読む必要があります。

「依存関係の参照をdependencyManagementセクションと照合するための最小限の情報セットは、実際には{groupId、artifactId、type、classifier}です。多くの場合、これらの依存関係は分類子のないjarアーティファクトを参照します。typeフィールドのデフォルトはjarであり、デフォルトの分類子はnullであるため、これにより、IDセットを{groupId、ArtifactId}に短縮できます。[ https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html ]

したがって、依存関係要素のすべてのサブ要素(スコープ、除外など)は、バージョンだけでなく、groupId、artifactId、type、classifierを除き、その時点でロックダウン/デフォルトに使用できます(したがって、以降)、dependencyElement内で依存関係を指定します。typeおよびclassifierサブエレメント(最初に引用したWebページを参照してすべてのサブエレメントを確認)で依存関係をそれぞれjarおよびnot nullとして指定した場合、{groupId、artifactId、classifier、type}が必要になります。 dependencyManagement要素から発生した継承の任意の時点でその依存関係を参照(解決)します。それ以外の場合、分類子とタイプ(それぞれjarとnull)のデフォルトをオーバーライドするつもりがない場合は、{groupId、artifactId}で十分です。したがって、デフォルトはその定義では適切なキーワードです。サブエレメント(groupId以外)

そのため、dependencyManagement要素への参照として、またはスタンドアロンとして、dependencyManagementの外部にあるすべての依存関係要素はすぐに解決されます(つまり、ローカルリポジトリにインストールされ、クラスパスで使用可能になります)。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.