maven---5依赖

  • maven项目中需要使用到其它依赖时,则需要在pom.xml中配置<dependency>元素也就是依赖声明,这样在编写项目时就可以使用依赖了,并且会在打包时自动将依赖的jar包打包到项目中。

1.依赖声明

  • 一个依赖声明可以包含如下的一些元素。
<project>
  <dependencies>
    ...
    <dependency>
      <groupId>...</groupId>
      <artifactId>...</artifactId>
      <version>...</version>
      <type>...</type>
      <scope>...</scope>
       <optional>...</optional>
        <exclusions>
           <exclusion>
            ...
            </exclusion>
         </exclusions>
    </dependency>
     ...
  </dependencies>
</project>
  • gourpId、artifactId、version:依赖的基本坐标,必须填写,maven根据这3个信息找到需要的依赖。

  • type:依赖的类型,大部分情况是jar,默认是jar。

  • scope :依赖的范围,后面详解。

  • optional: 标记依赖是否可选,值为true或false,默认为false, 如果为可选依赖,则依赖不具有传递性。即B->X(可选依赖),A->B。此时A的依赖中不包含X。

  • exclusions:用来排除传递性依赖。

大部分依赖声明只包含基本坐标,然而在一些特殊情况下,其他元素至关重要。

2.依赖范围

  • classpath:用于指定.class文件存放的位置,类加载器会从该路径中加载所需的.class文件到内存中。详细看类加载器

  • maven在编译项目主代码时需要使用一套classpath ,比如在使用spring框架的项目中,项目主代码需要用到spring-core依赖,scope为compile。该文件以依赖的方法被引入到classpath中。

  • maven在编译和执行测试代码时会使用另一套classpath。比如JUint,scope为test,该文件以依赖的方式引入到测试使用的calsspath中。

  • maven实际运行项目时又会使用一套classpath,上面的spring-core需要在该classpath中,而JUnit不需要。

maven依赖范围就是用来控制依赖与这三种classpath(编译classpath、测试classpath、运行classpath)的关系。
编译classpath:编译主代码有效
测试classpath:编译、运行测试代码有效
运行classpath:项目运行时有效

  • maven的依赖范围:

  • compile
    编译依赖范围。(默认方式),有效范围:编译classpath+测试classpath+运行classpath
    比如:spring-core,在编译测试运行阶段都需要使用。

  • test
    测试依赖范围。有效范围:测试classpath
    比如:JUnit,只在测试时使用,在编译主代码和运行时不需要此依赖。

  • provided
    已提供依赖范围。有效范围:编译classpath+测试classpath。
    比如:servlet-api。编译和测试项目时候需要该依赖,但在运行项目时,由于web容器已经提供,就不需要maven重复引入一遍了。

  • runtime
    运行时依赖范围。有效范围:测试classpath+运行classpath
    比如:JDBC驱动实现(mysql-connector-java),项目主代码编译时只需要JDK提供的JDBC接口,只有在执行测试或者运行项目时候才需要具体的JDBC驱动。

  • system
    系统依赖范围。有效范围:编译classpath+测试classpath
    使用system范围的依赖时必须通过systemPath元素显示地指定依赖文件的路径,因为此类依赖不是通过maven仓库解析的,而且往往与本地及其系统绑定,可能造成构建的不可移植,慎用。systemPath元素可以引用环境变量。
    比如:

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

3.依赖传递

  • 一个maven项目A依赖spring-core依赖范围为compile,因为spring-core又依赖 commons-logging依赖范围为compile,那么commons-logging就会成为A的compile范围依赖,commons-logging就是A的一个传递性依赖。

假设A依赖与B,B依赖与C,则A对于B是第一直接依赖,B对于C是第二直接依赖,A对于C是传递性依赖。第一直接依赖的范围和第二直接依赖的范围决定了传递性依赖的范围。如下表,最左边是第一直接依赖范围,上面是第二直接依赖范围,中间交叉单元格表示传递性依赖范围。

第一直接依赖\第二直接依赖 compile test provided runtime
compile compile - - runtime
test test - - test
provided provided - provided provided
runtime runtime - - runtime
  • 规律:
    • 第二直接依赖范围是compile时,传递依赖的范围与第一直接依赖范围一致。
    • 第二直接依赖范围是test时,依赖不会传递
    • 第二直接依赖范围是provided时,只传递第一直接依赖为provided的依赖。
    • 第二直接依赖范围是runtime时,传递依赖的范围与第一直接依赖范围一致,但是compile例外,此时传递依赖范围为runtime。

4.依赖优先

当C依赖A和B后,如果A和B的依赖中存在相同的依赖,那么C会依赖A中传递性依赖还是B中的传递性依赖呢?在maven中有两个原则来解决这一问题,第一原则解决不了才会使用第二原则。
C->A
C->B

  • 第一原则:路径最近者优先

A和B对于E的依赖情况
A->M(1.2)->E(1.3)
B->E(1.5)
C对于E的依赖情况。
C->A,B =>C->E1.5
C->B,A =>C->E1.5

  • 第二原则:第一声明者优先
    A->D(1.2)
    B->D(1.3)

C->A,B =>C->D(1.2)
C->B,A =>C->D(1.3)

5.可选依赖

  • 假设A依赖B,B依赖X和Y,依赖范围都是compile,但是B对于X和Y的依赖都是可选依赖,此时X,Y对于A而言不会传递。
    B->X(可选)
    B->Y(可?。?br> A->B

  • 什么情况下使用可选依赖?如果一个项目实现了两个特性,其中一个特性依赖X,另一个依赖Y,而这两个特性是互斥的,用户不可能同时使用两个特性。

  • 比如B是一个持久层隔离工具包,它支持多种数据库,包括mysql、PostgreSQL等,在构建这个工具包时需要这两种数据库驱动依赖,但是在A项目中使用这个工具包B时,A只会依赖一种数据库,因为mysql、PostgreSQL依赖不会传递到A,所以A要在单独配置一下依赖的 数据库。

6.排除依赖

传递性依赖会给项目引入很多依赖,简化项目依赖管理,但是也会带来问题

  • 需求
  • 比如当前项目有一个第三方依赖,而第三方依赖依赖了另一个类库的SNAPSHOT版本,那么这个SNAPSHOT就会成为当前项目的传递性依赖,而SNAPSHOT的不稳定性会直接影响到当前项目。这时候就应该排除掉SNAPSHOT。并且声明该类库的正式发布版本。
  • 由于版权原因一些类库不在中央仓库中,你想要替换掉它。
  • 当前项目需要依赖B(1.2),而当前项目又没有显示声明B(1.2),而是通过传递性依赖引入了B(1.0),此时就会出现问题,这时就需要来排除低版本的依赖或者显示声明。
  • 想显示声明某些必要的依赖,而不使用传递依赖,这样更方便查看和管理,而且如果依靠传递依赖,当依赖升级后有可能传递性依赖就不存在了。
       <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>3.6.10.Final</version>
              <exclusions>
                <exclusion>
                    <groupId>slf4j-api</groupId>
                    <artifactId>slf4j-api</artifactId>
                </exclusion>
             </exclusions>
         </dependency>  
         <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.12</version>
         </dependency>  
  • 上述代码中hibernate-validator依赖slf4j-api,但是当前项目不想使用传递过来的slf4j-api,所以通过exclusions声明排除依赖,exclusions可以包含多个exclusion元素。当前项目声明了自己需要的1.7.12版本的slf4j-api

7.归类依赖

  • 需求
    关于springframework的依赖有好多,org.springframework:spirng-core:2.5.6、org.springframework:sprng-beans:2.5.6、org.springframework:spring-context:2.5.6、org.springframework:spring-context-support:2.5.6,,他们来自同一个项目不同???,因此版本都是相同的,可以预见在升级spring时这些依赖都会一起升级,为了方便统一所以使用properties元素定义maven属性。
    如下:
<project>
....
 <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <springframework.version>4.3.2.RELEASE</springframework.version>
  </properties>

  <dependencies>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${springframework.version}</version>
      </dependency>
      <dependency>
           <groupId>org.springframework</groupId>
           <artifactId>spring-beans</artifactId>
           <version>${springframework.version}</version>
       </dependency>
       <dependency>
           <groupId>org.springframework</groupId>
           <artifactId>spring-core</artifactId>
           <version>${springframework.version}</version>
       </dependency> 
       <dependency>
           <groupId>org.springframework</groupId>
           <artifactId>spring-web</artifactId>
           <version>${springframework.version}</version>
       </dependency>
  </dependencies>
  ...
</project>
  • 通过使用${springframework.version}替换掉实际值,将所有spring依赖的版本值都使用这一引用值表示。

8.优化依赖

  • 需求
    在开发过程中,程序员应该对程序的依赖有清楚的了解,知道程序中都会有哪些依赖,并且不断的优化,去掉多余的依赖,显示声明必要的依赖。
    为此可以借助一些maven命令帮助我们更好的优化自己的依赖

8.1查看已解析依赖

  • maven会自动解析项目所有直接依赖和传递依赖,并根据规则和依赖范围确保任何一个构件只有唯一的版本在依赖中存在。在这些工作之后,最后得到的依赖被称为已解析依赖(Resolved Dependency)。

  • 查看当前项目已解析依赖:mvn dependency:list

iqasweb项目的所有已解析依赖,有省略

8.2 查看依赖树

  • 在已解析依赖的信息上还能查看到彼此的依赖关系,将直接在Pom.xml声明的依赖定义为顶层依赖,而顶层依赖的依赖为第二层依赖,依次类推还有第三层第四层依赖。经过maven解析后会构成一个依赖树,通过树就可以查看某个依赖是通过哪条路径引入的。

  • 查看命令:mvn dependency:tree

查看iqasweb项目依赖树

8.3分析依赖树

  • 在依赖树基础上还可以分析当前项目的依赖,分析会得到两个结果:
  • 一个是说明项目中使用到的,但是没有显示声明的依赖
  • 一个是说明项目中未使用的,但显示声明的依赖(没使用是指没有在编译主代码和测试代码中使用到的依赖,所以有可能项目运行中会使用到,需要自己分析)

*分析命令:mvn dependency:analyze

分析依赖
  • 在执行 maven-dependency-plugin:2.8:analyze目标之前会执行依次执行如下任务
    maven-resources-plugin:2.7:resources
    maven-compiler-plugin:3.3:compile
    maven-resources-plugin:2.7:testResources
    maven-compiler-plugin:3.3:testCompile
    即分析结果是依赖对主代码和测试代码进行编译后的到的。

  • 结果分析
    分析结果有如下两个部分:

  • Used undeclared dependencies found:说明项目中使用到的,但是没有显示声明的依赖。

  • Unused declared dependencies found:一个是说明项目中未使用的,但显示声明的依赖,没使用是指没有在编译主代码和测试代码中使用到的依赖,所以有可能项目运行中会使用到,需要自己分析,所以对于该依赖不应直接删除,需要分析,比如mysql:mysql-connector-java:jar:5.1.37:compile依赖在测试和编译时候不会用到,但是在运行时会用到。

  • 有什么不懂的一起探讨一下吧,我也是在学习的路上。喜欢给我点个赞吧(哈哈),我会继续努力的。
最后编辑于
?著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,029评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,238评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事?!?“怎么了?”我有些...
    开封第一讲书人阅读 159,576评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,214评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,324评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,392评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,416评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,196评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,631评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,919评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,090评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,767评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,410评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,090评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,328评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,952评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,979评论 2 351

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,644评论 18 139
  • Spring Boot 参考指南 介绍 转载自:https://www.gitbook.com/book/qbgb...
    毛宇鹏阅读 46,796评论 6 342
  • 文章作者:Tyan博客:noahsnail.com 2.Introduction to the Spring Fr...
    SnailTyan阅读 5,387评论 7 56
  • Maven简单介绍 Maven是一个项目管理工具。强大,但是很容易使用。 它包含了: 一个项目对象模型 (Proj...
    高公子Daniel阅读 4,230评论 4 60
  • 坐标 maven管理项目依赖的底层基?。辍W暝兀篻roupId、artifactId、version、pa...
    破晓追风阅读 446评论 0 0