我爱编程Maven

(V)Maven依赖

2018-06-11  本文已影响0人  SonyaBaby

依赖详解

<project>
...
 <dependencies>
   <dependency>
     <groupId></groupId>
     <artifactId></artifactId>
     <version></version>
     <type></type>
     <scope></scope>
     <optional></optional>
     <exclusions>
         <exclusion><exclusion>
         ...
     </exclusions>
   </dependency>
   ...
 <dependencies>
</project>

groupId、artifactId、version依赖的基本坐标,对任何一个依赖来说坐标是最重要的,Maven根据坐标才能找到所需要的依赖


type是依赖的类型,对应项目坐标定义的packaging。大部分情况下该元素不必声明,默认为jar


scope依赖范围:
Maven在编译项目主代码的时候要用一套编译classpath,这个时候域范围为compile;在执行测试的时候会使用另外一套测试classpath,域范围为test;实际运行Maven项目的时候,又会使用一套运行classpath

<dependency>
  <groupId>javax.sql</groupId>
  <artifactId>jdbc-stdext</artifactId>
  <version>2.0</version>
  <scope>system</scope>
  <systemPath>${java.home}/lib/rt.jar</systemPath>
</dependency>

optional依赖是否可选。当前有四个项目的依赖关系A→B(项目A依赖于项目B),B→X(可选),B→Y(可选)。根据传递性依赖定义,若这三个依赖范围都是compile,那么X,Y也是A的compile范围传递性依赖。这里由于XY都是可选依赖,依赖就不会传递。即XY对A不会有任何影响。

<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.play.myMaven</groupId>
    <artifactId>project-b</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          <version>5.1.34</version>
          <optional>true</optional>
        </dependency>
        <dependency>
          <groupId>com.oracle</groupId>
          <artifactId>ojdbc14</artifactId>
          <version>10.2.0.1.0</version>
          <optional>true</optional>
        </dependency>
    </dependencies>
</project>

在这个例子中,它们只会对当前项目B产生影响,当其他项目依赖于B的时候,这两个依赖不会被传递。当项目A依赖于项目B时,如果是基于MySQL数据库,那么在项目A中需要显式的声明mysql-connector-java这一依赖:

<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.play.myMaven</groupId>
    <artifactId>project-a</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
          <groupId>com.play.myMaven</groupId>
          <artifactId>project-b</artifactId>
          <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          <version>5.1.34</version>
        </dependency>
    </dependencies>
</project>

更好的做法是为MySQL/Oracle分别创建一个Maven项目,基于相同的groupId,分配不同的artifactId,在各自的POM中声明对应的JDBC驱动依赖,不使用可选依赖,用户根据需要选择使用对应artifactId。


exclusions用来排除传递性依赖。传递性依赖会隐式地引入很多依赖。对于一些隐式的不稳定版本依赖和需要替换的传递性依赖,都需要手动排除。例如

<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.play.myMaven</groupId>
    <artifactId>project-a</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
          <groupId>com.play.myMaven</groupId>
          <artifactId>project-b</artifactId>
          <version>1.0-SNAPSHOT</version>
          <exclusions>
            <exclusion>
                <groupId>com.play.myMaven</groupId>
                <artifactId>project-c</artifactId>
            </exclusion>
          </exclusions>
        </dependency>
        <dependency>
          <groupId>com.play.myMaven</groupId>
          <artifactId>project-c</artifactId>
          <version>1.10</version>
        </dependency>
    </dependencies>
</project>
排除依赖.png

项目A对项目C版本1.10的传递依赖,同时排除了B的传递依赖项目C


依赖调解
例如:项目A有这样的依赖关系:A→B→C→X(1,0)、A→D→X(2,0),X是A的传递性依赖,但是两条依赖路径上有两个版本的X,哪个X会被Maven解析?
Maven依赖调解的第一原则:路径最近者优先。X(2,0)路径为2,X(1,0)路径为3,X(2,0)被解析。
但如果是:A→B→Y(1,0)、A→C→Y(2,0),Y(1,0)和Y(2,0)依赖长度相同时,怎么解析呢?
Maven依赖调解的第一原则:第一声明者优先。在POM中依赖声明的顺序决定了谁会被先解析使用。


归类依赖
例如很多关于Spring Framework的依赖,为了避免重复书写同一项目的不同模块的版本,同时可以方便查看个构件版本,我们使用Maven属性归类依赖。

<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.play.myMaven</groupId>
    <artifactId>project-a</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
      <springframework.version>5.0.5.RELEASE</springframework.version>
    </properties>

    <dependencies>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-core</artifactId>
          <version>${springframework.version}</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context</artifactId>
          <version>${springframework.version}</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context-support</artifactId>
          <version>${springframework.version}</version>
        </dependency>
    </dependencies>
</project>

通过在properties中定义一个xxx.version子元素,用${xxx.version}来引用这一属性值。


优化依赖
对依赖进行优化:去除多余的依赖,显式地声明某些必要依赖。
Maven可以自动解析所有项目的直接依赖和间接依赖,并根据规则正确判断每个依赖的范围,对于一些依赖冲突,也能进行调解,以确保任何一个构件只有唯一的版本在依赖中存在。在这些之后,最后得到的那些依赖被称为已解析依赖。查看当前项目的已解析依赖,可以运行mvn dependency:list

[INFO] The following files have been resolved:
[INFO]    org.springframework:spring-web:jar:4.3.7.RELEASE:compile
[INFO]    org.springframework.boot:spring-boot-test:jar:1.5.2.RELEASE:test
[INFO]    com.fasterxml.jackson.core:jackson-annotations:jar:2.8.0:compile
[INFO]    org.hamcrest:hamcrest-library:jar:1.3:test
[INFO]    org.mockito:mockito-core:jar:1.10.19:test
[INFO]    org.springframework:spring-test:jar:4.3.7.RELEASE:test
[INFO]    org.slf4j:jul-to-slf4j:jar:1.7.24:compile
[INFO]    org.assertj:assertj-core:jar:2.6.0:test
[INFO]    org.springframework:spring-expression:jar:4.3.7.RELEASE:compile
[INFO]    com.icegreen:greenmail:jar:1.3.1b:test
[INFO]    org.skyscreamer:jsonassert:jar:1.4.0:test
...
[INFO]    org.springframework.boot:spring-boot:jar:1.5.2.RELEASE:compile
[INFO]    net.minidev:accessors-smart:jar:1.1:test
[INFO]    org.springframework:spring-context-support:jar:4.3.7.RELEASE:compile
[INFO]    com.fasterxml:classmate:jar:1.3.3:compile
[INFO]    ch.qos.logback:logback-classic:jar:1.1.11:compile
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

想要看的更清晰,可以以依赖树的方式,看到某个依赖是通过哪条路径引入的。运行:mvn dependency:tree

[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building parent 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:2.10:tree (default-cli) @ hello-maven ---
[INFO] com.play.myMaven:hello-maven:jar:1.0-SNAPSHOT
[INFO] +- org.springframework:spring-core:jar:5.0.5.RELEASE:compile
[INFO] |  \- org.springframework:spring-jcl:jar:5.0.5.RELEASE:compile
[INFO] +- org.springframework:spring-context:jar:5.0.5.RELEASE:compile
[INFO] |  +- org.springframework:spring-aop:jar:4.3.7.RELEASE:compile
[INFO] |  +- org.springframework:spring-beans:jar:4.3.7.RELEASE:compile
[INFO] |  \- org.springframework:spring-expression:jar:4.3.7.RELEASE:compile
[INFO] +- org.springframework:spring-context-support:jar:5.0.5.RELEASE:compile
[INFO] +- mysql:mysql-connector-java:jar:5.1.34:compile
[INFO] +- com.oracle:ojdbc14:jar:10.2.0.1.0:compile
[INFO] +- junit:junit:jar:4.11:test
[INFO] |  \- org.hamcrest:hamcrest-core:jar:1.3:test
[INFO] +- javax.mail:mail:jar:1.4.1:compile
[INFO] |  \- javax.activation:activation:jar:1.1:compile
[INFO] +- com.icegreen:greenmail:jar:1.3.1b:test
[INFO] |  \- org.slf4j:slf4j-api:jar:1.7.24:compile
...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

除此,我们还可以通过mvn dependency:analyze分析当前项目的依赖

[INFO] --- maven-dependency-plugin:2.10:analyze (default-cli) @ hello-maven ---
[WARNING] Used undeclared dependencies found:
[WARNING]    org.springframework.boot:spring-boot:jar:1.5.2.RELEASE:compile
[WARNING]    org.springframework:spring-beans:jar:4.3.7.RELEASE:compile
[WARNING]    org.springframework.boot:spring-boot-autoconfigure:jar:1.5.2.RELEASE:compile
[WARNING] Unused declared dependencies found:
[WARNING]    org.springframework.boot:spring-boot-starter-test:jar:1.5.2.RELEASE:test
[WARNING]    org.springframework.boot:spring-boot-starter-web:jar:1.5.2.RELEASE:compile
[WARNING]    com.oracle:ojdbc14:jar:10.2.0.1.0:compile
[WARNING]    mysql:mysql-connector-java:jar:5.1.34:compile
[WARNING]    org.springframework.boot:spring-boot-configuration-processor:jar:1.5.2.RELEASE:compile
[WARNING]    org.springframework:spring-core:jar:5.0.5.RELEASE:compile
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

注:《Maven实战》学习笔记

上一篇 下一篇

猜你喜欢

热点阅读