web-dev-qa-db-ja.com

DependencyManagementとMavenの依存関係の違い

dependencyManagementdependenciesはどう違いますか?私は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を定義する必要があるのでしょうか。必要なモジュールで直接定義しないのはなぜですか。

601
hguser

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

dependencyManagementのもう1つの非常に重要なユースケースは、推移的な依存関係で使用される成果物のバージョンの管理です。これは例がないと説明するのが難しいです。幸いなことに、これはドキュメントに示されています。

385
Pascal Thivent

私はファッショナブルにこの質問に遅れていますが、私はそれが受け入れられたものよりも明確な回答の価値があると思います(それは正しいですが、あなたがあなた自身を推測する必要がある実際の重要な部分を強調しません).

親POMでは、<dependencies><dependencyManagement>の主な違いは次のとおりです。

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

<dependencyManagement>セクションで指定された成果物は、それらが子モジュール自体の<dependencies>セクションでも指定されている場合にのみ、子モジュールに含まれます。なぜあなたはそれが良いのですか?これは、親でバージョンやスコープを指定し、子POMで依存関係を指定するときにそれらを除外できるためです。これは、各子モジュールでバージョンを指定せずに、子モジュールの依存関係に統一バージョンを使用するのに役立ちます。

565
dcoder

Mavenサイトの ドキュメント は恐ろしいものです。 dependencyManagementが行うことは、依存関係の定義(バージョン、除外など)を単純に親pomに移動し、次に子pomにgroupIdとartifactIdを追加するだけです。これで終わりです(親のpomチェーニングなどは除きますが、それほど複雑ではありません。dependencyManagementが親レベルの依存関係を排除します - ただし、それについて質問がある場合またはインポートする場合は、Mavenのドキュメントのほうが少し優れています)。

Mavenサイト上の 'a'、 'b'、 'c'のゴミをすべて読み、混乱した後、私はそれらの例を書き直しました。したがって、共通の依存関係(betaShared)を共有する2つのプロジェクト(proj1とproj2)がある場合は、その依存関係を親pomに移動できます。作業中に、他の依存関係(alphaとcharlie)を上に移動することもできますが、それはプロジェクトにとって意味がある場合に限られます。したがって、前の文で概説した状況については、親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>
44
MattC

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

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

最後に、dependencyManagementを使用して、複数のプロジェクトで使用する成果物の標準バージョンを定義できます。

43
Pran

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

これが増分の例です。

私はparent pomで宣言します。

__コード__

ブーム!私の<dependencies> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>19.0</version> </dependency> </dependencies> Child AそしてChild Bモジュールにそれがあります。

  • 子供のポンポンに継承された黙示録
  • 管理する単一の場所
  • 子供用ポンポンで何も再宣言する必要はありません
  • 必要に応じて、Child Cの中でversion 18.0を再配布してChild Bにオーバーライドすることもできます。

しかし、Child Cにguavaが不要になり、将来的にChild DおよびChild Eモジュールにも不要になった場合はどうなりますか。

それでも継承されますが、これは望ましくありません。これは、Java God Objectのコードの匂いに似ています。ここでは、クラスから有用な情報を継承しています。

これが<dependencyManagement>が登場するところです。これをあなたの親pomに追加すると、あなたのすべての子モジュールは見えなくなりますになります。ですから、あなたはそれを必要とする個々のモジュールのそれぞれに行き、それを再び宣言するのは強制です(ただしバージョンなしでChild AChild B)。

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

26
Andrejs

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

ただし、簡潔に説明した点はほとんどありません。

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

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

9
Mustafa Güven

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

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

6
IamVickyAV

親POMでは、<dependencies><dependencyManagement>の主な違いは次のとおりです。

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

セクションで指定された成果物は、それらが子モジュール自体のセクションでも指定されている場合にのみ、子モジュールに含まれます。なぜあなたはそれが良いのですか?これは、親でバージョンやスコープを指定し、子POMで依存関係を指定するときにそれらを除外できるためです。これは、各子モジュールでバージョンを指定せずに、子モジュールの依存関係に統一バージョンを使用するのに役立ちます。

4
Yaver

2つの違いは、Maven Webサイトのドキュメントで利用可能な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およびnullではないとして指定した場合、{groupId、artifactId、classifier、type}が必要です。 dependencyManagement要素から発生する継承の任意の時点で、その依存関係を参照(解決)します。それ以外の場合、分類子およびタイプのデフォルト(それぞれjarおよびnull)をオーバーライドするつもりがない場合は、{groupId、artifactId}で十分です。そのため、その定義ではデフォルトが適切なキーワードです。依存関係を参照するポイントで明示的に割り当てられた値(groupId、artifactId、classifier、typeを除く)は、dependencyManagement要素のデフォルトをオーバーライドします。

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

1
rps

Eclipseでは、dependencyManagementにもう1つの機能があります。 dependenciesがそれなしで使用されると、pomファイル内で見つけられなかった依存関係が注目されます。 dependencyManagementが使用されている場合、未解決の依存関係はpomファイル内で気付かれずに残り、エラーはJavaファイル内にのみ表示されます。 (輸入品等)

1
Gangnus