为什么我的项目中的库版本与父pom声明不同?

时间:2019-09-17 10:38:42

标签: spring maven spring-boot

我简化了项目结构并找到了一些线索。我的项目结构如下:

-------- project 1 ---------
parent
     |_ project-a
        |_ src
        |_ pom.xml
     |_ pom.xml

------- project 2 ----------
project-b
     |_ src
     |_ pom.xml

---------------------------

在项目1中,父级是项目-a的maven父级,它的pom.xml如下所示:

<?xml version="1.0" encoding="UTF-8"?>

<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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <!-- spring boot parent -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.6.RELEASE</version>
        <relativePath/>
    </parent>
    <groupId>com.demo</groupId>
    <artifactId>parent</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>A custom project using myfaces</name>
    <url>http://www.myorganization.org</url>

    <modules>
        <module>project-a</module>
    </modules>

    <dependencies>
    </dependencies>
</project>

在parent的pom中,它将spring boot声明为maven parent,并将project-a声明为模块。在project-a中,它的pom如下:

<?xml version="1.0" encoding="UTF-8"?>

<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">
    <parent>
        <artifactId>parent</artifactId>
        <groupId>com.demo</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>project-a</artifactId>
    <packaging>jar</packaging>
    <name>project-a Maven Webapp</name>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
    </properties>
    <dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.11</version>
            <scope>runtime</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.0</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <testSource>1.8</testSource>
                    <testTarget>1.8</testTarget>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-source-plugin</artifactId>
                <version>3.0.1</version>
                <executions>
                    <execution>
                        <id>attach-sources</id>
                        <goals>
                            <goal>jar</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

project-b是一个独立的项目,它的pom如下所示:

<?xml version="1.0" encoding="UTF-8"?>

<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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <!-- parent declaration is the key point of this problem! -->
    <parent>
        <artifactId>parent</artifactId>
        <groupId>com.demo</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <groupId>com.demo</groupId>
    <artifactId>project-b</artifactId>
    <packaging>jar</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>A custom project using myfaces</name>
    <url>http://www.myorganization.org</url>

    <!-- Project dependencies -->
    <dependencies>
        <dependency>
            <groupId>com.demo</groupId>
            <artifactId>project-a</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

    <build>
        <finalName>${project.artifactId}</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <executable>true</executable>
                    <classifier>exec</classifier>
                    <includeSystemScope>true</includeSystemScope>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

通过 mvn install 安装项目1后,项目b的依赖关系树如下:

[INFO] --- maven-dependency-plugin:3.1.1:tree (default-cli) @ project-b ---
[INFO] com.demo:project-b:jar:1.0-SNAPSHOT
[INFO] \- com.demo:project-a:jar:1.0-SNAPSHOT:compile
[INFO]    \- mysql:mysql-connector-java:jar:8.0.16:runtime

但是,如果我删除了project-b的pom中的父声明,那么我期望的是project-b的依赖树:

[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ project-b ---
[INFO] com.demo:project-b:jar:1.0-SNAPSHOT
[INFO] \- com.demo:project-a:jar:1.0-SNAPSHOT:compile
[INFO]    \- mysql:mysql-connector-java:jar:8.0.11:runtime

在重新安装项目1之后,我还尝试在项目1父项的pom中删除spring boot的父项依赖项,结果也是我所期望的。所以我猜父声明是关键,但是为什么呢?

最好的问候。

1 个答案:

答案 0 :(得分:0)

这是因为父项的依赖项比项目a的项具有更高的优先级。
您可以参考此文档。
https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html

  

依赖关系调解-确定遇到多个版本作为依赖项时将选择工件的哪个版本。 Maven选择了“最近的定义”。也就是说,它使用依赖关系树中最接近您的项目的版本。您始终可以通过在项目的POM中明确声明版本来保证版本。请注意,如果两个依赖关系版本在依赖关系树中的深度相同,则第一个声明将获胜。

     

“最近的定义”表示所使用的版本将在依赖关系树中最接近您的项目。例如,如果将A,B和C的依赖关系定义为A-> B-> C-> D 2.0和A-> E-> D 1.0,则在构建A时将使用D 1.0,因为从A出发的路径通过E到D的时间更短。您可以在A中向D 2.0显式添加一个依赖项,以强制使用D 2.0。

<artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.6.RELEASE</version>

由于该模块还具有mysql-connector-java(8.0.16)的依赖关系,因此maven使用它而不是project-a的依赖项。

https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-parent/2.1.6.RELEASE

project-b
parent
|----mysql-connector-java(8.0.16)   <- maven choose this because its level is higher
|----project-a
     |----mysql-connector-java(8.0.11)

也许是这样..? (请让我知道我是否想念)