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实战》   

  • 相关阅读:
    HDU1029 Ignatius and the Princess IV
    UVA11039 Building designing【排序】
    UVA11039 Building designing【排序】
    POJ3278 HDU2717 Catch That Cow
    POJ3278 HDU2717 Catch That Cow
    POJ1338 Ugly Numbers(解法二)
    POJ1338 Ugly Numbers(解法二)
    UVA532 Dungeon Master
    UVA532 Dungeon Master
    POJ1915 Knight Moves
  • 原文地址:https://www.cnblogs.com/xiaohang123/p/15181810.html
Copyright © 2011-2022 走看看