1. 概要

このチュートリアルでは、2つの重要な Mavenタグ-dependencyManagementdependencies)を確認します。

これらの機能は、マルチモジュールプロジェクトで特に役立ちます。

2つのタグの類似点と相違点を確認し、開発者がそれらを使用するときに混乱を引き起こす可能性のあるいくつかの一般的な間違いについても確認します。

2. 使用法

一般に、dependencies タグで依存関係を定義するときに、versionタグとscopeタグが繰り返されないように、dependencyManagementタグを使用します。 このようにして、必要な依存関係が中央のPOMファイルで宣言されます。

2.1. 依存関係管理

このタグは依存関係タグで構成されており、それ自体に複数の依存関係タグが含まれている可能性があります。 各依存関係には、 groupId ArtifactId、、およびversionの少なくとも3つのメインタグが必要です。 例を見てみましょう:

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

上記のコードは、新しいアーティファクト commons-lang3 を宣言しているだけですが、実際にはプロジェクトの依存関係リソースリストに追加されていません。

2.2. 依存関係

このタグには、dependencyタグのリストが含まれています。 各依存少なくとも2つのメインタグがあるはずです。 groupId ArtifactId。

簡単な例を見てみましょう:

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

以前にPOMファイルでdependencyManagementタグを使用したことがある場合は、バージョンタグとスコープタグを暗黙的に継承できます

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

3. 類似点

これらのタグは両方とも、サードパーティまたはサブモジュールの依存関係を宣言することを目的としています。 それらは互いに補完し合っています。

実際、通常、dependencyManagementタグをdependenciesタグの前に1回定義します。 これは、POMファイルで依存関係を宣言するために使用されます。 この宣言は単なる発表であり、プロジェクトへの依存関係を実際に追加するものではありません。

JUnitライブラリの依存関係を追加するためのサンプルを見てみましょう。

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

上記のコードでわかるように、dependencyManagementタグがあります。このタグ自体に別の依存関係タグが含まれています。

次に、プロジェクトに実際の依存関係を追加するコードの反対側を見てみましょう。

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

したがって、現在のタグは前のタグと非常によく似ています。 それらの両方が依存関係のリストを定義します。 もちろん、すぐにカバーする小さな違いがあります。

同じgroupIdタグとartifactIdタグが両方のコードスニペットで繰り返されており、それらの間には意味のある相関関係があります。どちらも同じアーティファクトを参照しています。

ご覧のとおり、後のdependencyタグにはversionタグはありません。 驚いたことに、それは有効な構文であり、問題なく解析およびコンパイルできます。 理由は簡単に推測できます。dependencyManagementによって宣言されたバージョンを使用します。

4. 違い

4.1. 構造の違い

前に説明したように、これら2つのタグの主な構造上の違いは、継承のロジックです。 dependentencyManagement タグでバージョンを定義すると、指定せずに上記のバージョンを使用できます次の依存関係タグにあります。

4.2. 行動の違い

dependentencyManagementは単なる宣言であり、実際には依存関係を追加しません。このセクションで宣言されたdependencies は、後でdependenciesタグで使用する必要があります。 実際の依存関係を発生させるのは、依存関係タグだけです。 上記のサンプルでは、dependencyManagementタグはjunitライブラリをどのスコープにも追加しません。 これは、将来の依存関係タグの単なる宣言です。

5. 実際の例

ほぼすべてのMavenベースのオープンソースプロジェクトがこのメカニズムを使用しています。

Mavenプロジェクト自体の例を見てみましょう。 Mavenプロジェクトに存在するhamcrest-core依存関係が表示されます。 最初にdependencyManagementタグで宣言され、次にメインのdependenciesタグによってインポートされます。

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.hamcrest</groupId>
            <artifactId>hamcrest-core</artifactId>
            <version>2.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>org.hamcrest</groupId>
        <artifactId>hamcrest-core</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

6. 一般的な使用例

この機能の非常に一般的なユースケースは、マルチモジュールプロジェクトです。

さまざまなモジュールで構成される大きなプロジェクトがあると想像してください。 各モジュールには独自の依存関係があり、各開発者は使用される依存関係に異なるバージョンを使用する場合があります。 次に、さまざまなアーティファクトバージョンのメッシュが発生する可能性があります。これにより、競合が困難になり、解決が困難になる可能性もあります。

この問題の簡単な解決策は、ルートPOMファイル(通常は「親」と呼ばれます)でdependentencyManagement タグを使用し、次に子のPOMファイル(サブモジュール)、さらには親モジュール自体(該当する場合)。

モジュールが1つしかない場合、この機能を使用するのは理にかなっていますか? これはマルチモジュール環境では非常に便利ですが、シングルモジュールプロジェクトでもベストプラクティスとして従うことも経験則になります。 これにより、プロジェクトが読みやすくなり、マルチモジュールプロジェクトに拡張できるようになります。

7. よくある間違い

よくある間違いの1つは、dependentencyManagement セクションで依存関係を定義し、dependenciesタグに依存関係を含めないことです。 この場合、前述のスコープに応じて、コンパイルエラーまたはランタイムエラーが発生します。

例を見てみましょう:

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

上記のPOMコードスニペットを想像してみてください。 次に、このライブラリをサブモジュールのソースファイルで使用するとします。

import org.apache.commons.lang3.StringUtils;

public class Main {

    public static void main(String[] args) {
        StringUtils.isBlank(" ");
    }
}

ライブラリがないため、このコードはコンパイルされません。 コンパイラはエラーについて文句を言います:

[ERROR] Failed to execute goal compile (default-compile) on project sample-module: Compilation failure
[ERROR] ~/sample-module/src/main/java/com/baeldung/Main.java:[3,32] package org.apache.commons.lang3 does not exist

このエラーを回避するには、以下のdependenciesタグをサブモジュールPOMファイルに追加するだけで十分です。

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

8. 結論

このチュートリアルでは、MavenのdependentencyManagementタグとdependenciesタグを比較しました。 次に、それらの類似点と相違点を確認し、それらがどのように連携するかを確認しました。

いつものように、これらの例のコードはGitHubから入手できます。