zoukankan      html  css  js  c++  java
  • Maven学习(二) -- 坐标和依赖

    标签(空格分隔): 学习笔记


    坐标

    实际就像在几何中,我们用一对坐标(x, y)来表示坐标系中唯一的点;或者我们可以用(经度,纬度)来表示地球上的某一个位置,在Maven的世界中,有坐标来唯一的表示项目。

    他们由groupId, artifactId, version, packaging, classifier等信息唯一的标识。

    依赖

    Maven会根据在POM中妹纸的信息自动下载所需要的依赖构件。

    依赖的配置

    <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: 依赖的范围。
    • optional: 标记依赖是否可选;
    • exclusions: 用来排除传递性依赖。

    依赖范围

    这里的依赖范围主要针对上面scope而言。 Maven在编译项目主代码的时候需要使用一套classpath,其中,编译,测试,运行使用不同的classpath。

    依赖范围就是用来控制依赖于这三种classpath(编译classpath,测试classpath,运行classpath)的关系的。。。

    • compile: 编译依赖范围。如果没有指定,则默认使用该依赖范围。使用此依赖范围的Maven依赖,对于编译,运行,测试三种classpath都有效。典型的例子是spring-core.
    • test: 测试依赖范围。典型的例子是JUnit.
    • provided: 已提供依赖范围。对于编译和测试classpath有效,而对运行classpath无效。典型的例子是servlet-api,编译和测试项目的时候需要该依赖,但在运行项目的时候,由于容器已经提供,就不需要Maven重复的引入了。
    • runtime: 运行时依赖范围。对于测试和运行都有效。典型的例子是JDBC。在项目编译的时候只需要JDK提供JDBC接口,只有在运行或测试的时候才需要实现上述接口的具体JDBC驱动。
    • system: 系统依赖范围。编译和测试时有效,应是无效。但使用system范围的依赖时必须通过systemPath元素显示地指定依赖文件的路径。由于此类依赖不是通过Maven仓库解析的,而且往往与本机系统绑定,可能造成构建的不可移植,因此应谨慎使用。
    • import: 导入依赖范围。

    传递性依赖

    一个机遇Spring Framework的项目,如果不使用Maven,则在项目中就需要手动下载相关依赖: 做法一:下载一个很大的如spring-framework-2.5.6-with-dependencies.zip的包,这里包含了所有Spring Frame的jar包,以及依赖的所有其他jar包,但这样往往会导致引入了很多不必要的依赖; 做法二:只下载spring-framework-2.5.6.zip的包,到实际应用的时候根据其出错信息,再依次下载其他的包。 上面两种做法实际都是很繁琐的,在Maven中可以使用依赖性传递来解决这个问题。Maven会解析各个直接依赖的POM。将那些必要的间接依赖,以传递性依赖的形式引入到当前的项目中。

    排除传递性依赖

    例如如下场景:

    • 场景一:当前项目中有一个第三方依赖,而这个第三方依赖由于某些原因依赖了另外一个类库的SNAPSHOT版本(该类库就成了项目的传递依赖),而SNAPSHOT可能是不稳定的,则必然会影响到该项目的稳定性,因此希望能够将这个传递依赖切除。
    • 场景二:希望能够替换某个传递性依赖。例如一个项目A依赖一个类库X,而由于版本的原因,这个类库并不在中央仓库中。但是某个公司有个类似的实现包Y。所以我们想做的是将X的依赖切除,然后声明对Y的依赖。

    排除传递性依赖实例:

    <project>
        <modelVersion>4.0.0</modelVersion>
        <groupId>com.park.mvnDemo</groupId>
        <artifactId>project-a</artifactId>
        <version>1.0.0</version>
        <dependencies>
            <dependency>
                <groupId>com.park.mvn</groupId>
                <artifactId>project-b</artifactId>
                <version>1.0.0</version>
                <exclusions>
                    <exclusion>
                        <groupId>com.park.mvnDemo</groupId>
                        <artifactId>project-c</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <dependency>
                <groupId>com.park.mvnDemo</groupId>
                <artifactId>project-c</artifactId>
                <version>1.0.0</version>
            </dependency>
        </dependencies>
    </project>
    

    需要注意的是:声明exclusions的时候只需要groupId和artifactId,而不需要version,就可以唯一的定位依赖图中的某个依赖。(Maven解析后,不可能出现groupId和artifactId相同,但version不同的两个依赖。)

    依赖调解

    • 第一原则:路径最近者优先;
    • 第二原则:第一声明优先。
    • 在依赖路径长度相等的前提下,在POM中依赖声明的顺序决定了谁会被解析使用,顺序最靠前的那个依赖优胜。

    在理想情况下,是不应该使用可选依赖的。使用的原因是:某一个项目实现了多个特性,而且这些特性间是互斥的。

    可选依赖不被传递

    假设有这样一个依赖关系: 项目A依赖于项目B,项目B依赖于项目X和Y,而且B对X和Y的依赖都是可选依赖:A->B, B->X(可选), B->Y(可选)。此时,X,Y将不会对A有任何影响,即可选传递不会传递下去。 可选依赖的配置:

    <project>
        <modelVersion>4.0.0</modelVersion>
        <groupId>com.juven.mvnDemo</groupId>
        <artifactId>project-b</artifactId>
        <version>1.0.0</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>
    </project>
    

    归类依赖

    类似与Java中的常量定义,Maven中的依赖也应该在一个唯一的地方定义版本,并且在dependency声明中引用这一版本。这样,在升级一些包的时候只需要修改一处。 实例:

    <project>
        <modelVersion>4.0.0</modelVersion>
        <groupId>com.park.mvnDemo.account</groupId>
        <artifactId>account-email</artifactId>
        <name>Account Email</name>
        <version>1.0.0</version>
        
        <properties>
            <springframework.version>2.5.6</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-beans</artifactId>
                <version>${springframework.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>${springframework.version}</version>
            </dependency>
        </dependencies>
    </project>
    

    这里,使用<properties> <springframework.version>2.5.6</springframework.version> </properties>定义一个Maven属性,然后后面使用${springframework.version}来使用这个属性。

    优化依赖

    Maven会自动解析所有项目的直接依赖和传递性依赖,并且根据规则正确判断每个依赖的范围,对于一些依赖冲突,也能进行调节,以确保任何一个构件只有唯一的版本在依赖中存在。-- 得到的依赖成为已解析依赖(Resolved Dependency)

    • 查看项目中的已解析依赖:
    • 使用命令mvn dependency:list
    • 查看当前项目中的依赖树:
    • 使用命令mvn dependency:tree
    • 分析当前项目中的依赖:
    • 使用命令mvn dependency:analyze.

    如上便是Maven中依赖的主要内容。

  • 相关阅读:
    python-全局变量是否使用global总结
    python-多线程创建以及查看
    python-tcp客户端
    python-udp聊天器
    python-udp接受数据
    python-udp发送数据
    python-正则表达式总结
    JAVA程序员面试必知32个知识点
    计算机专业英语基础篇
    非常经典有深度的电影英文台词
  • 原文地址:https://www.cnblogs.com/little-YTMM/p/5973798.html
Copyright © 2011-2022 走看看