MAVEN02_依赖范围+依赖冲突+解决冲突+继承聚合(三)

④. 如何解决依赖冲突


①. 使用maven提供的依赖调解原则


①. 依赖调节原则 — 第一声明者优先原则(在 pom 文件中定义依赖,以先声明的依赖为准。其实就是根据坐标导入的顺序来确定最终使用哪个传递过来的依赖)


结论:通过上图可以看到,spring-aop和spring-webmvc都传递过来了spring-beans,但是因为spring-aop在前面,所以最终使用的spring-beans是由spring-aop传递过来的,而spring-webmvc传递过来的spring-beans则被忽略了


MAVEN02_依赖范围+依赖冲突+解决冲突+继承聚合(三)


②. 根据路径近者优先原则, 我们项目中引入的commons-logging为1.2


MAVEN02_依赖范围+依赖冲突+解决冲突+继承聚合(三)


③. 如果在同一个pom中引入了两个相同的jar包,以引入的最后一个为准

如下的配置引入的是1.2


    <dependencies>
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.1.2</version>
        </dependency>
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.2</version>
        </dependency>
    </dependencies>


②. 可选依赖optional


  • ①. 新建项目A(类似于mysql)、B(类似于oracle),项目C(类似于业务层,引入A、B工程),项目D(类似于逻辑工程,引入了C)

  • C项目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/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>mavenTest</artifactId>
        <groupId>com.xiaozhi</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>C</artifactId>

    <dependencies>
        <dependency>
            <groupId>com.xiaozhi</groupId>
            <artifactId>A</artifactId>
            <version>1.0-SNAPSHOT</version>
            <!-- optional=true,依赖不会传递,该项目依赖A
                之后依赖该项目的项目如果想要使用A,需要重新引入 -->
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>com.xiaozhi</groupId>
            <artifactId>B</artifactId>
            <version>1.0-SNAPSHOT</version>
            <optional>true</optional>
        </dependency>
    </dependencies>
</project>


MAVEN02_依赖范围+依赖冲突+解决冲突+继承聚合(三)


②. 画个图说明问题:


由于projectC使用到了两个来自projectA的类(OptionalFeatureAClass)和projectB的类(OptionalFeatureBClass).如果projectC没有依赖packageA和packageB,那么编译将会失败。


projectD依赖projectC,但是对于projectD来说,类(OptionalFeatureAClass)和类(OptionalFeatureBClass)是可选的特性,所以为了让最终的war/ejbpackage不包含不必要的依赖,使用optional声明当前依赖是可选的,默认情况下也不会被其他项目继承(好比Java中的final类,不能被其他类继承一样)


MAVEN02_依赖范围+依赖冲突+解决冲突+继承聚合(三)


③. 如果projectD确实需要用到projectC中的OptionalFeatureAClass怎么办呢?


那我们就需要在projectD的pom.xml中显式的添加声明projectA依赖,继续看下图ProjectD需要用到ProjectA的OptionalFeatureAClass,那么需要在ProjectD的pom.xml文件中显式的添加对ProjectA的依赖


MAVEN02_依赖范围+依赖冲突+解决冲突+继承聚合(三)


④. 到这也就很好理解为什么Maven为什么要设计optional关键字了,假设一个关于数据库持久化的项目(ProjectC),为了适配更多类型的数据库持久化设计,比如Mysql持久化设计(ProjectA)和Oracle持久化设计(ProjectB),当我们的项目(ProjectD)要用的ProjectC的持久化设计,不可能既引入mysql驱动又引入oracle驱动吧,所以我们要显式的指定一个,就是这个道理了


③. 排除依赖


  • 可以使用exclusions标签将传递过来的依赖排除出去


MAVEN02_依赖范围+依赖冲突+解决冲突+继承聚合(三)





上一篇:Maven·依赖范围·传递依赖·依赖冲突


下一篇:C# 网络编程之通过ip地址获取地理位置(补充)