Mavenでプロジェクトを管理していると、「同じライブラリなのにバージョンがバラバラ…」という状況に陥ることがあります。
特に複数のモジュールを持つプロジェクトでは、バージョンの統一が大変ですよね。
そんな問題を解決してくれるのがdependencyManagement(依存関係管理)という機能です。
今回は、Mavenのpom.xmlで使える<dependencyManagement>について、通常の<dependencies>との違いから実践的な使い方まで、初心者の方にも分かりやすく解説していきます。
dependencyManagementとは何か?

依存関係のバージョンを一元管理する仕組み
dependencyManagementは、Mavenで使用するライブラリ(依存関係)のバージョンを集中管理するための機能です。
pom.xmlの<dependencyManagement>セクションに記述することで、プロジェクト全体で使用するライブラリのバージョンを統一できます。
イメージで理解する:
通常の<dependencies>が「このライブラリを実際に使います」という宣言なら、<dependencyManagement>は「このライブラリを使う場合は、このバージョンを使ってね」というルールブックのようなものです。
dependenciesとの違い
この2つは似ているようで、明確な違いがあります。
<dependencies>:
- 実際に依存関係を追加する
- プロジェクトに直接影響する
- ビルド時にダウンロードされる
<dependencyManagement>:
- 依存関係のバージョン情報を定義するだけ
- それ自体では何もダウンロードされない
- 子プロジェクトや
<dependencies>で参照される
具体例で比較:
<!-- dependencyManagement:定義だけ -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
</dependency>
</dependencies>
</dependencyManagement>
<!-- dependencies:実際に使用 -->
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<!-- バージョン不要!上で定義されている -->
</dependency>
</dependencies>
<dependencyManagement>でバージョンを定義しておけば、<dependencies>ではバージョン番号を書かなくても良いんです。
なぜdependencyManagementが必要なのか?
バージョンの統一が困難
複数のモジュールを持つプロジェクトでは、同じライブラリを複数箇所で使います。
dependencyManagementなしの場合:
<!-- module-a/pom.xml -->
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>30.1-jre</version>
</dependency>
</dependencies>
<!-- module-b/pom.xml -->
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.1-jre</version> <!-- バージョンが違う! -->
</dependency>
</dependencies>
各モジュールで個別にバージョンを指定すると、統一が難しくなります。
バージョンアップの手間
ライブラリを更新する際、すべてのpom.xmlを修正する必要があります。
問題点:
- 修正箇所が多い
- 更新漏れが発生しやすい
- バージョン不整合が起きやすい
バージョン競合の発生
異なるバージョンが混在すると、予期しない動作やエラーが発生することがあります。
dependencyManagementを使うと:
- 親pom.xmlで一度だけバージョンを定義
- 子モジュールではバージョン指定不要
- バージョンアップも一箇所を変更するだけ
管理が劇的に楽になります。
基本的な使い方
単一プロジェクトでの使用
シンプルなプロジェクトでも、dependencyManagementは有効です。
pom.xmlの例:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>my-app</artifactId>
<version>1.0.0</version>
<!-- バージョン情報をプロパティで定義 -->
<properties>
<spring.version>5.3.20</spring.version>
<junit.version>4.13.2</junit.version>
</properties>
<!-- 依存関係のバージョンを管理 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!-- 実際に使用する依存関係 -->
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<!-- バージョン不要 -->
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<!-- バージョン不要 -->
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
<!-- バージョン不要 -->
</dependency>
</dependencies>
</project>
メリット:
- バージョンが一箇所にまとまって見やすい
- バージョンアップが簡単
- プロパティと組み合わせると更に便利
マルチモジュールプロジェクトでの活用
親子構造での使用
複数のモジュールを持つプロジェクトで真価を発揮します。
プロジェクト構造:
parent-project/
├── pom.xml (親POM)
├── module-a/
│ └── pom.xml
├── module-b/
│ └── pom.xml
└── module-c/
└── pom.xml
親POMの設定
parent-project/pom.xml:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>parent-project</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<!-- 子モジュールの定義 -->
<modules>
<module>module-a</module>
<module>module-b</module>
<module>module-c</module>
</modules>
<!-- バージョン情報 -->
<properties>
<spring-boot.version>3.0.0</spring-boot.version>
<lombok.version>1.18.24</lombok.version>
<junit.version>5.9.0</junit.version>
</properties>
<!-- 依存関係の統一管理 -->
<dependencyManagement>
<dependencies>
<!-- Spring Boot BOM -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- その他のライブラリ -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
子モジュールの設定
module-a/pom.xml:
<project>
<modelVersion>4.0.0</modelVersion>
<!-- 親POMを継承 -->
<parent>
<groupId>com.example</groupId>
<artifactId>parent-project</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>module-a</artifactId>
<!-- 依存関係の追加(バージョン不要) -->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!-- バージョンは親POMで管理 -->
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<!-- バージョンは親POMで管理 -->
</dependency>
</dependencies>
</project>
module-b/pom.xml:
<project>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.example</groupId>
<artifactId>parent-project</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>module-b</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<!-- 同じSpring Bootバージョンが適用される -->
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
すべての子モジュールで、統一されたバージョンが自動的に適用されます。
BOM(Bill of Materials)の活用

BOMとは
BOM(Bill of Materials)は、「部品表」という意味で、関連するライブラリのバージョンをまとめて定義したpom.xmlのことです。
Spring BootやSpring Cloudなど、多くのフレームワークがBOMを提供しています。
BOMのインポート
<scope>import</scope>と<type>pom</type>を使って、BOMをインポートできます。
例:Spring Boot BOMの使用
<dependencyManagement>
<dependencies>
<!-- Spring Boot BOMをインポート -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>3.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- バージョン指定不要!BOMで管理されている -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
</dependencies>
複数のBOMを組み合わせ
複数のBOMを同時にインポートすることもできます。
<dependencyManagement>
<dependencies>
<!-- Spring Boot BOM -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>3.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- Spring Cloud BOM -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2022.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- AWS SDK BOM -->
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>bom</artifactId>
<version>2.19.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
各BOMで定義されているライブラリを、すべてバージョン指定なしで使えます。
バージョンの上書き
dependencyManagementで定義したバージョンを変更
特定のモジュールだけ異なるバージョンを使いたい場合、明示的にバージョンを指定できます。
親POM:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>30.1-jre</version>
</dependency>
</dependencies>
</dependencyManagement>
子POM:
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.1-jre</version> <!-- 上書き -->
</dependency>
</dependencies>
子POMで明示的にバージョンを指定すると、親の定義より優先されます。
exclusionとの組み合わせ
特定の推移的依存関係を除外することもできます。
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>3.0.0</version>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</dependencyManagement>
TomcatではなくJettyを使いたい場合などに便利です。
バージョン競合の解決
依存関係ツリーの確認
どのバージョンが実際に使われているか確認できます。
コマンド:
mvn dependency:tree
出力例:
[INFO] com.example:my-app:jar:1.0.0
[INFO] +- org.springframework:spring-core:jar:5.3.20:compile
[INFO] | \- org.springframework:spring-jcl:jar:5.3.20:compile
[INFO] \- junit:junit:jar:4.13.2:test
依存関係の階層構造が表示されます。
バージョン競合の検出
mvn dependency:tree -Dverbose
競合している依存関係が詳しく表示されます。
dependencyManagementで解決
競合するライブラリを<dependencyManagement>で明示的に指定します。
<dependencyManagement>
<dependencies>
<!-- 競合しているライブラリのバージョンを固定 -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
</dependencyManagement>
これで、すべてのモジュールで統一されたバージョンが使われます。
ベストプラクティス
プロパティでバージョン管理
バージョン番号をプロパティとして定義すると、変更が容易になります。
<properties>
<!-- Java バージョン -->
<java.version>17</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<!-- ライブラリバージョン -->
<spring-boot.version>3.0.0</spring-boot.version>
<lombok.version>1.18.24</lombok.version>
<jackson.version>2.14.0</jackson.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
scopeも一緒に定義
バージョンだけでなく、scopeも<dependencyManagement>で定義できます。
<dependencyManagement>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope> <!-- scopeも定義 -->
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
</dependencies>
</dependencyManagement>
子POMでは、groupIdとartifactIdだけ書けばOKです。
BOMを積極的に活用
主要なフレームワークはBOMを提供しているので、活用しましょう。
メリット:
- 相互に互換性のあるバージョンが保証される
- 個別にバージョンを調べる手間が不要
- フレームワークの推奨設定が適用される
Gradleでの同等機能
MavenのdependencyManagementに相当する機能は、GradleではプラットフォームやBOMとして提供されます。
Gradleの例:
// build.gradle
dependencies {
// BOMをインポート
implementation platform('org.springframework.boot:spring-boot-dependencies:3.0.0')
// バージョン指定不要
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
testImplementation 'org.junit.jupiter:junit-jupiter'
}
Kotlinの場合:
// build.gradle.kts
dependencies {
implementation(platform("org.springframework.boot:spring-boot-dependencies:3.0.0"))
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
testImplementation("org.junit.jupiter:junit-jupiter")
}
よくある質問
dependencyManagementは必須?
いいえ、必須ではありません。
ただし、以下の場合は強く推奨されます:
- マルチモジュールプロジェクト
- 複数のライブラリを統一的に管理したい
- チーム開発
- 大規模プロジェクト
親POMがない場合は使えない?
単一プロジェクトでも使えます。
親子関係がなくても、同じpom.xml内で<dependencyManagement>と<dependencies>を併用できます。
BOMと直接バージョン指定、どちらが優先?
優先順位:
<dependencies>で明示的に指定したバージョン(最優先)<dependencyManagement>で指定したバージョン- 推移的依存関係で引き込まれたバージョン
明示的な指定が常に優先されます。
複数のBOMで競合したら?
先に定義されたBOMが優先されます。
<dependencyManagement>
<dependencies>
<!-- これが優先される -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>3.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- 競合した場合、こちらは無視される -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.7.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
まとめ:dependencyManagementで効率的な依存関係管理を
dependencyManagementは、Mavenプロジェクトのライブラリバージョンを一元管理するための強力な機能です。
特にマルチモジュールプロジェクトでは必須と言えます。
この記事のポイント:
- dependencyManagementは依存関係のバージョンを定義する場所
- 通常のdependenciesとは異なり、それ自体はダウンロードしない
- 親POMで定義し、子モジュールで参照する
- BOMをインポートすると多数のライブラリを一括管理できる
- プロパティと組み合わせると更に便利
- バージョン競合を防ぎ、統一的な管理が可能
- scopeや除外設定も定義できる
- 子POMで明示的に指定すれば上書き可能
- dependency:treeで依存関係を確認
- Gradleではplatformを使用
最初のステップ:
- 既存のpom.xmlを確認
- dependencyManagementセクションを追加
- バージョン情報をプロパティに移動
- dependenciesからバージョン指定を削除
dependencyManagementを使いこなせば、プロジェクトの保守性が格段に向上します。
最初は少し面倒に感じるかもしれませんが、プロジェクトが大きくなるほど、その恩恵を実感できますよ。
効率的な依存関係管理で、快適な開発ライフを実現しましょう!


コメント