kagamihogeの日記

kagamihogeの日記です。

spring-bootでspring-mvcの依存性が解決される仕組みを調べる

spring-bootでは、例えば以下のようにparentとdependencyを指定しておけば、spring-webとかspring-mvcとかの依存性をよしなに解決してくれる。以下のように書くとspring-webmvc-5.2.1.RELEASE.jarが解決されるが、このエントリではそれがどのようにして行われるのか? を勉強したメモを残しておく。

 <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.1.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

spring-boot-starter-webのdependencies

まず、spring-boot-starter-webpom.xmlを見るとspring-webmvcdependencyがあるのが分かる。ただしversionについては記載が無い。よって、parentであるspring-boot-starter-parentの親子階層を見ていく。

 <dependencies>
        <!--  省略 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
        </dependency>
    </dependencies>

spring-boot-parentの階層

次に、parentで指定するspring-boot-starter-parentの親子階層から見ていく。

spring-boot-starter-parentは上記のような階層になっている。また、spring-boot-starter-webspring-boot-starter-testは、spring-boot-parentの子のspring-boot-startersのmodule、という構造になっている。

spring-boot-buildでspring-framework-bomをimport

spring-webmvcのversionは親階層のどこかで指定しているハズだが、ここでには直接書かれてはいない。

まず、以下のようにspring-framework-bomdependencyManagementでimportしている。

 <properties>
        <!-- 省略 -->           
        <spring-framework.version>5.2.2.BUILD-SNAPSHOT</spring-framework.version>
        <!-- 省略 -->
    </properties>
    <dependencyManagement>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-framework-bom</artifactId>
                <version>${spring-framework.version}</version>
                <scope>import</scope>
                <type>pom</type>
            </dependency>

spring-framework-bom-5.2.1.RELEASE*1をimportしている。で、ここで具体的なversionと共にspring-webmvcが書いてある。

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.springframework</groupId>
  <artifactId>spring-framework-bom</artifactId>
  <version>5.2.1.RELEASE</version>
  <packaging>pom</packaging>
  <name>Spring Framework (Bill of Materials)</name>
 <!-- 省略 -->
<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>5.2.1.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>5.2.1.RELEASE</version>
    </dependency>

基本的にはこのようなparent・importの関係によってdepedencyが解決されるのが分かる。

bomとdependencyManagementで必要なライブラリだけ使用する

spring-framework-bom-5.2.1.RELEASEには様々なspring関連ライブラリが並んでいるが、spring-boot-starter-webだけだとspring-webspring-mvcしか使われない。これはmavenのbomという仕組みを使用している。

bomとは、ライブラリ提供者が複数ライブラリのversionの意図した組み合わせ、を記述したもの。使用者はそこから必要なものだけを使用するが、これはmavanのdependencyManagementで実現する。これは名前の通りdependencyを管理するもので、dependencyManagementをparenで親子関係にしたりimportしたりしてもdependencyとして解決されず、<dependencies><dependency>...を記述すると依存性として解決される。ただし、versionは省略出来てdependencyManagementのversionが使用される。これによって、使用者は必要なライブラリだけ、かつ、開発者が意図したversionのものを使用できる。

なお、上記のbomやdependencyManagementの解説はあくまで自分の言葉で書いたものなので、詳細な定義が必要な場合は公式リファレンス等を参照してください。

まとめ

というわけで、

  1. spring関連ライブラリのbomをimport
  2. そのversionはparenの親子関係で指定

のようなタテ・ヨコの関係を駆使した構造になっている。

*1:上記xmlでは5.2.2だが何か無いので解説のため5.2.1を使用