Maven依赖的配置

Maven的依赖配置有基本的groupId,artifactId和version等元素组成,其实一个依赖声明可以包含如下的 
一些元素 
    <project> 
        ... 
        <dependencies> 
            <dependency> 
                <groupId>...</groupId> 
                <artifactId>...</artifactId> 
                <version>...</version> 
                <type>...</type> 
                <scope>...</scope> 
                <optional>...</optional> 
                <exclusions> 
                    <exclusion> 
                    ... 
                    </exclusion> 
                <exclusions> 
            </dependency> 
            ... 
        <dependencies> 
    </projects>

依赖元素介绍 
    根元素project下的dependencies可以包含一个或者多个dependency元素,以声明一个或多个 
    项目依赖。每个依赖可以包含的元素有: 
    groupId,artifactId和version:依赖的基本坐标,对于任何一个依赖来说,基本坐标是最重要 
        的,Maven根据坐标才能找到需要的依赖。

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

    scope:依赖的范围,如test,compile,provided

    optional:标记依赖是否可选

    exclusions:用来排除传递性依赖

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

依赖范围 
    Maven在编译项目主代码的时候需要使用一套classpath.

    Maven在编译和执行测试的时候会使用另外一套classpath。

    Maven实际运行项目的时候,又会使用一套classpath。

    依赖范围就是用来控制依赖与这三种classpath(编译classpath,测试classpath,运行classpath)的关系, 
    Maven有以下几种依赖范围: 
    compile:编译依赖范围,如果没有指定,就会默认使用该依赖范围。使用此依赖范围的Maven依赖,对于编译,测试,运行三种 
        classpath都有效。典型的例子是spring-core

    test:测试依赖范围。使用此依赖范围的Maven依赖,只对于测试classpath有效。典型的例子是JUnit

    provided:已提供依赖范围。使用此依赖范围的Maven依赖,对于编译和测试classpath有效,但在运行时无效 
        典型的例子是:servlet-api,编译和测试项目的时候需要该依赖,但在运行项目的时候,由于容器已经提供,就不需要 
        Maven重复地引入一遍。

    runtime:运行时依赖范围,使用此依赖范围的Maven依赖,对于测试和运行classpath有效,但在编译主代码时无效。 
        典型的例子是JDBC驱动实现,项目主代码的编译只需要JDK提供的JDBC接口,只有在执行测试或者运行项目的时候才需要实现 
        上述接口的具体JDBC驱动。

    systemm:系统依赖范围。该依赖范围与三种classpath的关系,和provided依赖范围完全一致。但是,使用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>

    import:(Maven2.0.9及以上):导入依赖范围,该依赖范围不会对三种classpath产生实际的影响,此依赖范围只在dependencyManagement 
        元素下才有效,使用该范围的依赖通常指向一个pom,作用是将目标POM中的dependencyManagement配置导入并合并到当前POM的 
        dependencyManagement元素中。

        import范围依赖由于其特殊性,一般都是指向打包类型的pom的模块,如果有多个项目,它们使用 
        的依赖版本都是一致的,则就可以定义一个使用dependencyManagement专门管理依赖的POM,然后 
        在各个项目中导入这些依赖管理配置

        <dependencyManagement> 
            <dependencies> 
                <dependency> 
                    <groupId>com.catt.account</groupId> 
                    <artifactId>account-parent</artifactId> 
                    <version>1.0-SNAPSHOT</version> 
                    <type>pom</type> 
                    <scope>import</scope> 
                </dependency> 
            </dependencies> 
        </dependencyManagement>

传递性依赖和依赖范围 
    依赖范围不仅可以控制依赖与三种classpath的关系,还对传递性依赖产生影响。 
    如account-email对于spring-core的依赖范围是compile,spring-core对于commons-logging的依赖范围是compile,那么account-email对于commons-logging 
    这一传递性依赖的范围也就是compile。 
    假设A依赖于B,B依赖于C,则A对于B是第一直接依赖,B对于C是第二直接依赖,A对于C是传递性依赖。第一直接依赖的范围和第二直接依赖的范围决定了传递性 
    依赖的范围

    Maven会解析各个直接依赖的POM,将那些必要的间接依赖以传递性依赖的形式引入到当前的项目中。

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

依赖调解 
    Maven引入的传递性依赖机制,一方面大大简化和方便了依赖声明,另一方面,大部分情况下我们只需要关心项目的直接依赖是什么,而不用考虑这些直接依赖会引入 
    什么传递性依赖。但有时候,当传递性依赖造成问题的时候,就需要清楚地知道该传递性依赖是从哪条依赖路径引入的

    依赖调解(Dependency Mediation)的原则有两个,如下:(为了避免针对同个构件的重复引入) 
    第一原则:路径最近者优先 
    第二原则:第一声明优先。 即在依赖路径长度相等的前提下,在POM中依赖声明的顺序决定了谁会被解析使用,顺序最靠前的那个依赖优先。

可选依赖 
    假设有这样一个依赖关系,项目A依赖于项目B,项目B依赖于项目X和项目Y,B对于项目X和Y的依赖都是可选依赖。根据传递性依赖的定义,如果所有这三个依赖的范围都是 
    compile,那么X\Y就是A的compile范围传递性依赖,然而,由于这里X\Y是可选依赖,依赖将不会得以传递,换句话说,X\Y将不会对A有任何影响。

    在理想的情况下,是不应该使用可选依赖的。 
    使用可选依赖的原因是某一个项目实现了多个特性,如项目是一个持久层隔离工具包,支持多种数据如MYSQL,SYBASE,在构建这个工具包的时候,需要这两种数据库的驱动 
    程序,但在使用这个工具包的时候,只会依赖一种数据库。

排除依赖 
    传递性依赖会给项目隐式地引入很多依赖,这极大的简化了项目依赖的管理,但有时这种特性也会带来问题。

    声明exclusion的时候只需要groupId和artifactId,而不需要version元素,这是因为只需要groupId和artifactId就能唯一确定依赖图中的某个依赖。

    排除依赖: 
    排除不稳定的传递性依赖构件,另外再显式在当前项目中声明该类库的某个正式发布的版本。 
    想替换某个传递性依赖,比如Sun JTP API,Hibernate依赖于这个JAR,但是由于版本的因素,该类库不在中央仓库中,而Apache Geronimo项目有一个对应的实现 
        这时就可以排除Sun JAT API,再声明Geronimo的JTA API的实现

归类依赖 
    如果一个项目依赖同一项目的多个不同模块,如一个项目依赖springframework的多个模块,因为这些依赖的版本都是相同的,且可以预见,如果将来需要升级,则这些 
    依赖的版本会一直升级。

    这样可以定义maven的属性,然后通过${}的方式引用

优化依赖: 
    Maven会自动解析所有项目的直接依赖和传递性依赖,并且根据规则正确判断每个依赖的范围,对于一些依赖, 
    也能进行调节,以确保任何一个依赖只有唯一的版本在依赖中存在,在这些工作之后,最后得到的那些依赖被称为 
    已解析依赖(Resolved Dependency). 可以运行如下命令查看当前项目的已解析依赖 
    mvn dependency:list 
    mvn dependency:tree 
    mvn dependency:analyze

坐标和依赖是任何一个构件在Maven世界中的逻辑表达方式;而构件的物理表示方式是文件,Maven通过仓库来统一管理这些文件

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值