依存推移的
現在のプロジェクトは依存関係を導入しており、この依存関係の依存関係もプロジェクトにインポートされます。より正確には、maven
直接的な依存関係を解決しPOM
、それらの必要な間接的な依存関係を推移的な依存関係の形で現在のプロジェクトに導入します。
なぜ「必要な間接依存」と呼ばれるのか? これは、すべての間接的な依存関係がインポートされるわけではないためです。これは、依存maven
の範囲について話さなければなりません。
依存範囲
maven
jar
依存関係の導入とは、パッケージをプロジェクトにコピーすることではなく、jar
パッケージをローカル ウェアハウスにダウンロードしてから、定式化を通じて特定のパッケージclasspath
をプロジェクトに導入することです。管理 3 セット、すなわちjar
maven
classpath
クラスパスをコンパイルし、クラスパスをテストし、クラスパスを実行します。
依存範囲は、3 つのクラスパスを制御するために使用されます。maven の依存範囲は次のとおりです。
依存範囲 | 例証する |
---|---|
コンパイル | 依存スコープをコンパイルします (デフォルト)。すべてのクラスパスに有効です。例:スプリングコア |
テスト | 依存スコープをテストします。テスト クラスパスに対してのみ有効です。例: ジュニット |
提供された | 従属スコープが提供されています。コンパイルおよびテスト クラスパスに有効です。例: サーブレット-api |
ランタイム | ランタイムはスコープに依存します。クラスパスのテストと実行に有効です。例: JDBC ドライバー |
システム | システム依存のスコープ。コンパイルおよびテスト クラスパスに有効です。systemPath を介して明示的に指定されます。 |
輸入 | 依存スコープをインポートします。クラスパスには影響しません。 |
クラスパスの制御に加えて、依存関係のスコープは依存関係の配信にも影響します。A が B に依存し、B が C に依存する場合、A は B の最初の直接依存関係です。B は、C に対する 2 番目の直接的な依存関係です。 A はCに対する推移的な依存関係です。結論としては、最初の直接依存の範囲と 2 番目の直接依存の範囲によって、推移的な依存の範囲が決まります。
「Maven Combat」の表を使用して説明します。
1 つ目は直接依存する 2 つ目は直接依存する | コンパイル | テスト | 提供された | ランタイム |
---|---|---|---|---|
コンパイル | コンパイル | - | - | ランタイム |
テスト | テスト | - | - | テスト |
提供された | 提供された | - | 提供された | 提供された |
ランタイム | ランタイム | - | - | ランタイム |
最初の列は最初の直接依存関係、最初の行は 2 番目の直接依存関係、中央は推移的な依存関係の範囲を示します。
依存関係の競合と依存関係の調停
依存関係の競合の可能性が生じるのは、依存関係の転送のためです。たとえば、A->X(1.0)、A->B->X(2.0) です。A は X のバージョン 1.0 に直接依存し、A が依存する B は X のバージョン 2.0 に依存します。依存範囲が適切であれば、B に依存する X も A プロジェクトに渡されます。2 つの X のバージョンに一貫性がないため、依存関係の競合が発生します。
依存関係の競合が発生した場合、maven は直接エラーを表示しませんが、一連のルールを使用して続行します仲介に頼る. 次の 2 つの規則があります。
- 最も近いパスが優先されます。
- 最初の宣言者が優先されます。
依存パスとは、プロジェクトから依存関係までの長さを指し、たとえば、A->X(1.0) の長さは 1、A->B->X(2.0) の長さは 2 なので、1.0 X のバージョンが最終的に使用されます。
両方のパスが同じ場合はどうなりますか? たとえば、A->B->X(2.0) と A->C->X(3.0) の場合、これら 2 つの依存関係パスの長さは 2 です。これには、最初に宣言された方を使用するという2 番目の規則が必要です。
ほとんどの場合、maven
この自動依存関係仲介は問題の解決に役立ちます。ただし、依存関係の競合を手動で処理する必要がある場合があります。この種の競合は、同じ依存関係の異なるバージョン (この依存関係のメディエーションで処理できます) ではなく、同時に現れることができない 2 つの依存関係である可能性があります。たとえばslf4j-log4j
、logback
これら 2 つの依存関係は同時に現れることはありませんが、それらの座標が異なるため、maven はそれらを処理のために整列しません。現時点では、手動で行う必要があります依存関係を除外する上。
依存関係の除外
以下の例は、依存関係を除外する例です。バージョンを指定する必要はありません:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.5.3</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
</exclusion>
</exclusions>
</dependency>
この種の除外は非常に便利です. 除外する必要がある同じ間接的な依存関係が多数ある場合は、さらに面倒です. Maven 実装の依存関係の「グローバルな除外」を参照してください.
依存関係の競合を確認する 依存
関係の競合が発生した場合、maven は依存関係の仲介を使用するため、プロンプトは表示されません。では、どうやって確認するのでしょうか。2 つの方法があります。
1 つ目は、mvn dependency:tree -Dverbose
プロジェクトのすべての依存関係と推移的な依存関係をリストすることです。依存関係が重複して競合している場合は、omitted for duplicate
プロンプトが表示されますomitted for conflict with x.x.x
。
2 番目の方法は、maven のエンフォーサ プラグインを使用することです。プロジェクト POM に追加します。
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>1.4.1</version>
<executions>
<execution>
<id>enforce</id>
<configuration>
<rules>
<dependencyConvergence/>
</rules>
</configuration>
<goals>
<goal>enforce</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
このように、maven でコンパイルする場合、依存関係の競合がある場合、エラー メッセージが表示されます。
[ERROR]
Dependency convergence error for org.slf4j:slf4j-api:1.6.1 paths to dependency are:
+-org.myorg:my-project:1.0.0-SNAPSHOT
+-org.slf4j:slf4j-jdk14:1.6.1
+-org.slf4j:slf4j-api:1.6.1
and
+-org.myorg:my-project:1.0.0-SNAPSHOT
+-org.slf4j:slf4j-nop:1.6.0
+-org.slf4j:slf4j-api:1.6.0