zoukankan      html  css  js  c++  java
  • Maven依赖管理

    Maven依赖管理

    一、依赖配置

    1. mave依赖通过groupId、artifactId和version来确定依赖的唯一性;
    2. type:大多数情况下不用声明,默认为jar;
    3. scope:指明依赖范围;
    4. optional:标记依赖是否可选;
    5. exclusions:排除传递性依赖;
    <project>
        ...
        <dependencies>
            ...
            <dependency>
                <groupId>...</groupId>
                <artifactId>...</artifactId>
                <version>...</version>
                <type>...</type>
                <scope>...</scope>
                <optional>...</optional>
                <exclusions>
                    <exclusion>
                    ...
                    </exclusion>
                    ...
                </exclusions>
            </dependency>
            ...
        </dependencies>
        ...
    <project>

    二、依赖范围

      首先需要知道maven有三套classpath,编译classpath、测试classpath和运行classpath。

    1. 编译classpath:指编译主代码会使用到的classpath,主代码即默认的src/main/java目录下的代码;
    2. 测试classpath:指编译和运行测试代码会用到的classpath,测试代码即默认的src/test/java目录下的代码;
    3. 运行classpath:运行主代码和打包时会用到的classpath,因为打包也是作为运行主代码所用,所以用的同一套classpath;

      使用不同的依赖范围scope,可将依赖放入不同的classpath,即会在不同的生命周期或阶段生效。

    1. compile:编译依赖范围。默认为此依赖范围,使用此依赖范围的maven依赖,对于编译、测试和运行三种classpath都有效;
    2. test:测试依赖范围。只对测试classpath有效,编译、运行主代码和打包时无效,如JUnit;
    3. provided:已提供依赖范围。对编译classpath和测试classpath有效,运行主代码和打包时无效,如Servlet-api;
    4. runtime:运行时依赖范围。对运行classpath和测试classpath有效,编译主代码时无效,如mysql-connect-java;
    5. system:系统依赖范围。和provided依赖范围一致,使用system范围的依赖需通过systemPath显式指定依赖文件的路径。默认打包后不存在,需增加额外配置
    6. import:导入依赖范围。和三种classpath没有关系。主要用来继承非父工程的依赖版本,springboot中比较常见。
    <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>2.2.2.RELEASE</version>
    </parent>
    
    <!-- 由于一个项目只能有一个父工程,所以可通过此方式继承其他工程的依赖版本-->
    <dependencyManagement>
      <dependencies>
        <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-dependencies</artifactId>
          <version>${spring-cloud.version}</version>
          <type>pom</type>
          <scope>import</scope>
        </dependency>
      </dependencies>
    </dependencyManagement>

      依赖范围与classpath的关系

    三、传递性依赖

      如果A依赖于B,B依赖于C,我们说A对B是第一直接依赖,B对C是第二直接依赖,A对C是传递性依赖。传递性依赖和第一直接依赖范围、第二直接依赖范围有关。

      最左边一列表示第一直接依赖范围,最上面一行表示第二直接依赖范围,则传递性依赖情况如下:

      为方便记忆,总结如下:

    1. 当第二直接依赖的范围是complie时,传递性依赖的范围与第一直接依赖的范围一致;
    2. 当第二直接依赖的范围是test时,依赖不会得以传递;
    3. 当第二直接依赖的范围provided时,只传递第一直接依赖范围也为provided的依赖,且传递性依赖的范围同样为provided;
    4. 当第二直接依赖的范围时runtime时,依赖性传递的范围与第一直接依赖的范围一致,但compile例外,此时传递性依赖的范围为runtime。

    四、依赖调解

      maven具有依赖调解机制,当碰到如这样的依赖关系:A -> B -> C -> X(1.0)、A -> D -> X(2.0),X是A的传递性依赖,maven会根据某些原则自主决定X的依赖版本,最终X的依赖版本只会有一个。

    1. 第一原则,路径最近者优先:在以上例子中,X(2.0)会被解析使用;
    2. 第二原则,第一声明者优先:当路径一样时,如:A -> B ->Y(1.0)、A -> C -> Y(2.0),如果B的依赖声明在C之前,则Y(1.0)会被解析使用。

      实际开发中,建议显式指明或排除相同依赖的版本,不应该依赖于maven的依赖调解机制。

    五、可选依赖

      通过optional标签指定,默认为false,即满足依赖传递的条件时,此依赖会被传递,显式指定为true时,此依赖不会被传递。

            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <optional>true</optional>
            </dependency>

    六、排除依赖

      由于某种原因,不想引入某个传递性依赖时,或发生依赖冲突时(即同一个groupId和artifactId存在不同的version时,不应依赖自动调解),可通过exclusions排除一个或多个传递性依赖。

      声明exclusion时只需要groupId和artifactId,因为maven解析后的依赖中,groupId和artifactId不会重复。

     

    七、归类依赖

      当需要依赖同一个工程的不同模块时,这些依赖的版本往往是相同的,此时可通过maven属性将版本号归类,达到避免重复、防止版本冲突、方便版本升级的目的。

      如很多对Spring Framework的依赖,可统一管理版本:

    <properties>
        <spring.version>4.1.3.RELEASE</spring.version>
    </properties>
    <dependencies>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context</artifactId>
          <version>${spring.version}</version>
        </dependency>
     
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-test</artifactId>
          <version>${spring.version}</version>
        </dependency>
     
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-beans</artifactId>
          <version>${spring.version}</version>
        </dependency>
     
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-webmvc</artifactId>
          <version>${spring.version}</version>
        </dependency>
     
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-jdbc</artifactId>
          <version>${spring.version}</version>
        </dependency>
    </dependencies>

    八、优化依赖

      经过maven的依赖传递机制和依赖调解,以及显式声明和排除依赖后,最终得到的那些依赖叫已解析依赖。可通过以下命令查看和优化已解析依赖:

    mvn dependency:list
    #查看已解析依赖

    mvn dependency:tree
    #查看依赖树,了解依赖传递信息
    #注意依赖树中显示的依赖范围表示对当前工程的依赖范围

    mvn dependency:analyze
    #分析依赖树
    #Used undeclared dependencies表示使用未显式声明的依赖
    #Unused declared dependencies表示未使用的显式声明的依赖
    #此命令只会分析编译主代码和测试代码需要用到的依赖,不分析运行测试代码和主代码的依赖,也就是说无法分析runtime依赖范围的依赖

      参考:《Maven实战》   

  • 相关阅读:
    简单的文件上传html+ashx
    URL重写
    图解classloader加载class的流程及自定义ClassLoader
    Linux下PS命令详解
    JAVA字符串格式化-String.format()的使用
    JAVA String.format 方法使用介绍
    MVC设计模式(Python)
    Jupyter NoteBook 的快捷键使用指南
    Hive常用函数
    Hive Tutorial(一)
  • 原文地址:https://www.cnblogs.com/xiaohang123/p/15181810.html
Copyright © 2011-2022 走看看