Maven(4)maven依赖

        Maven作为一个项目管理工具,其依赖管理功能十分强大,用好了Maven,就不再需要面对一大堆jar而感到头大,依赖冲突、无用依赖等问题也能够得到有效的防止和解决。

一、依赖的基本元素

Maven中一个依赖声明可以包括以下一些元素:
<dependency>
	<groupId>...</groupId>
	<artifactId>...</artifactId>
	<version>...</version>
	<type>...</type>
	<scope>...</scope>
	<optional>...</optional>
	<exclusions>
		<exclusion>
	              ...
		</exclusion>
	</exclusions>
</dependency>
groupId、artifactId和version:依赖的基本坐标。
type:依赖的类型,默认jar。
scope:依赖的范围。
optional:标记依赖是否可选。
exclusion:用来排除传递性依赖。

二、依赖范围

         Maven在编译项目主代码的时候需要使用一套classpath。其次,在编译和执行测试的时候会使用另外一套classpath。最后,实际运行Maven项目的时候,又会使用一套classpath。
所谓的依赖范围就是用来控制依赖与这三种classpath(编译、测试、运行)的关系,Maven有以下几种依赖范围:
(1)compile:
        编译依赖范围。如果没有指定,默认使用该依赖范围。使用此依赖范围时,对于编译、测试、运行都有效。例如:spring-core,编译、测试、运行时都需要使用该依赖。
(2)test:
        测试依赖范围。只对测试classpath有效。例如:JUnit,它只在编译测试代码以及运行测试的时候才需要,编译和运行classpath时无法使用此依赖。
(3)provided:
        已提供依赖范围。对于编译和测试时有效,但在运行时无效。例如:servlet-api,编译和测试项目的时候需要该依赖,但运行时,由于容器已经提供,就不需要Maven重复的引入。
(4)runtime:
        运行时依赖。编译时无效,对于测试和运行有效。例如:JDBC驱动实现,编译时只需要JDK提供的JDBC接口,只有在执行测试和运行时才需要实现上述接口的具体JDBC驱动。
(5)system:

        系统依赖范围。同provided。使用该依赖时必须通过systemPath元素显式地指定依赖文件路径。主要用于依赖本地的、且Maven仓库之外的类库文件。

这里归纳一下主要的依赖范围以及作用:

依赖范围(scope)主源码classpath可用测试源码classpath可用会被打包
compile 缺省值YYY
testNYN
runtimeNYY
providedYYN

三、传递性依赖

        Maven中,当项目依赖一个a.jar包时,如果a.jar包同时依赖b.jar包,那么只需要在pom中声明对a.jar的依赖即可,b.jar会被Maven自动加载进来。


        如上图所示,hibernate-core 依赖 hibernate-commons-annotations ,而 hibernate-commons-annotations 又依赖slf4j-api ,hibernate-core 对slf4j-api 的依赖就是传递依赖。我们只需要引入 hibernate-core 构件的依赖,不用考虑它还有其它的依赖, 也不用担心会引入多余或冲突的依赖,Maven 会自动为我们引入依赖及传递依赖。

依赖传递和依赖范围

        依赖范围不仅仅可以控制依赖与三种classpath的关系,还对传递性依赖产生影响。如上图 2.2 所示,几种依赖关系分别叫做第一直接依赖、第二直接依赖和传递性依赖,其中第一直接依赖和第二直接依赖的依赖范围,决定了传递性依赖的依赖范围。

当第二直接依赖的范围是compile的时候,传递性依赖的范围与第一直接依赖的范围一致;
当第二直接依赖的范围是test的时候,依赖不会得以传递;
当第二直接依赖的范围是provided的时候,只传递第一直接依赖范围也为provi的依赖,且范围为provided;
当第二直接依赖的范围是runtime的时候,传递性的依赖范围与第一直接依赖的范围一致,但compile例外,此时传递依赖范围为runtime;

依赖调解

    通常我们不需要关心传递性依赖,当多个传递性依赖中有对同一构件不同版本的依赖时,如何解决呢?
    原则一:路径最近者优先。例如:A ->B ->C ->X(1.0) 同时 A ->D ->X(2.0),很显然X(2.0)路径更短,会被解析使用。
    原则二:第一声明者优先。在依赖长度相等情况下,解析在pom中依赖声明中顺序考前的。例如:A ->B ->X(1.0) 同时 A ->D ->X(2.0)。如果B在D之前声明,那么X(1.0)会被解析。
可选依赖
例如:b.jar是一个持久层工具包,它同时支持Mysql和PostgreSql,A项目依赖b.jar,那么在构建A时需要这两种数据库的驱动程序,但在使用的时候知会依赖一种数据库。B项目的依赖声明如下:

<dependency>
  <groupId>com.xxx.xx</groupId>
  <artifactId>xx.db</artifactId>
  <version>2.5</version>
  <dependencies>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.10</version>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>postgresql</groupId>
      <artifactId>postgresql</artifactId>
      <version>8.4-701.jdbc3</version>
      <optional>true</optional>
    </dependency>
  </dependencies>
</dependency> 
使用<optional>元素表示这两个为可选依赖,这是依赖不会传递到A项目,当A项目需要使用基于MySQL数据库时,需要显式声明对mysql的依赖。
另外:在理想的情况下是不会出现这种情况的,因为在面向对象设计中,有一个单一职责原则,即一个jar的职责应该只有一个。所以对于b.jar,最好是创建2个Maven项目,分别实现mysql和postgresql。
排除依赖
当一个项目A依赖项目B,而项目B同时依赖项目C,如果项目A中因为各种原因不想引用项目C,在配置项目B的依赖时,可以排除对C的依赖。
依赖排除使用 <exclusions> 元素,exclusions中可以有多个exclusion,示例如下:
<dependency>
      <groupId>sample.ProjectB</groupId>
      <artifactId>Project-B</artifactId>
      <version>1.0-SNAPSHOT</version>
      <exclusions>
        <exclusion>
          <groupId>sample.ProjectE</groupId> <!-- Exclude Project-E from Project-B -->
          <artifactId>Project-E</artifactId>
        </exclusion>
      </exclusions>
 </dependency>
 注意:exclusion中只需要声明groupId、artifactId,而不需要version元素。
 依赖归类
 通常在项目中,我们会同时依赖同一个构件的不同模块,如 spring-orm-3.2.0,spring-context-3.2.0,且多个模块版本相同,为了维护和升级方便,我们可以对其同一管理,这时可以使用到 Maven 属性,类似于变量的概念。

<properties>
     <springframework.version>3.2.0.RELEASE</springframework.version>
 </properties>
 
 <dependencies>
     <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-orm</artifactId>
         <version>${springframework.version}</version>
     </dependency>
     <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-context</artifactId>
         <version>${springframework.version}</version>
     </dependency>
 </dependencies>

参考:
       [1]http://www.cnblogs.com/luotaoyeah/p/3784901.html
       [2]http://www.cnblogs.com/qt2136/p/4507725.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值