Maven实战读书笔记(三):Maven依赖

3.1 依赖的配置

一个依赖声明可以包含下面元素:

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

groupId、artifactId、version依赖的基本坐标。

type:依赖的类型,对应于项目坐标定义的packaging,默认:jar

scope:依赖的范围。

optional:标志依赖是否可选,true/false

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

3.2 依赖范围

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

Maven的依赖范围有如下几种:

compile:编译依赖范围,默认值,对三种classpath都有效。

test:测试依赖范围,只对测试classpath有效,典型例子如:Junit

provided:已提供依赖范围,对编译和测试classpath有效,但在运行时无效,典型例子如:servlet-api,运行时由容器提供。

runtime:运行时依赖范围,对测试和运行classpath有效,编译主代码时无效,典型例子如:JDBC驱动实现,编译时只需要JDK提供的JDBC接口,运行才需要具体的实现。

system:系统依赖范围,对编译和测试classpath有效,但在运行时无效。使用该范围时,必须通过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:导入依赖范围,该范围不会对三种classpath产生实际应用,会将目标POM中的dependencyManagement配置导入合并到当前POMdependencyManagement元素中。

3.3 传递性依赖和依赖范围

Maven的传递性依赖是指不需要考虑你依赖的库文件所需要依赖的库文件,能够将依赖模块的依赖自动的引入。

依赖的范围不仅可以控制依赖与三种classpath的关系,还会对传递性依赖产生影响。假设A依赖于B,B依赖于C,则说A对于B是第一直接依赖,B对C是第二直接依赖,A对于C是传递依赖。第一直接依赖范围和第二直接依赖范围决定了传递性依赖的范围,其结果如下:

  第二直接依赖范围是`compile`时,传递性依赖范围与第一直接依赖范围一致;
  第二直接依赖范围是`test`时,依赖不会得以传递;
  第二直接依赖范围是`provided`时,只传递第一直接依赖范围也为provided的;
  第二直接依赖范围是`runtime`时,传递性依赖的范围与第一直接依赖范围一致,`compile`例如,此时的传递性依赖范围为`runtime`。

3.4 依赖调解

一般情况下,只关心项目的直接依赖,而不关心直接依赖引入的传递性依赖,但当传递性依赖出现问题时,需要知道该传递性依赖是怎么引进来的。

Maven依赖调解第一原则:路径最近者优先,如:A->B->C->X(1.0)、A->D-X(2.0),则X的2.0版本会被解析使用;

Maven依赖调解第二原则:第一声明者优先,如:A->B->X(1.0)、A->D->X(2.0),若B的依赖声明在D之前,则使用X的1.0版本,否则使用X的2.0版本。

3.5 可选依赖

假设有下面的依赖关系:A->B、B->X(可选)、B->Y(可选),由于X和Y是可选的,所以依赖不会传递,X和Y不会对A有任何影响。

可选依赖的必要性:项目B实现2种特性,特性一依赖于X,特性二依赖于Y,而且这两个特性是互斥的,用户不可能同时适用这两个特性,这时候可选依赖就有用了。

原则上说,是不应该使用可选依赖的,根据面向对象的单一职责性原则,该原则同样适用于Maven项目的规划。

3.6 最佳实践

1)排除依赖

传递性依赖会给项目隐式的引入很多依赖,这极大的简化了项目依赖的管理,但是有时某些依赖会带来问题,这时需要把带来问题的依赖排除掉。

2)归类依赖

来自同一个项目的不同模块,其版本号应该是相同的,如springframework项目有spring-corespring-beans模块,对这些模块的版本号通过属性定义,再进行引用,这样可以进行版本的整体升级:

    <properties>
        <springframework.version>4.3.13.RELEASE</springframework.version>
    </properties>
    <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>

3)优化依赖

去掉多余的依赖,显示声明某些必要的依赖。

通过mvn dependency:list 查看项目已解析的依赖

通过mvn dependency:tree 查看项目的依赖树

原文地址:https://www.cnblogs.com/Jxwz/p/8372372.html

时间: 2024-10-13 15:15:12

Maven实战读书笔记(三):Maven依赖的相关文章

Maven实战读书笔记(8)

何为Maven的生命周期? 1.Maven从大量项目和构建工具中学习和反思,然后总结了一套高度完善的.易扩展的生命周期 2.这个生命周期包含了项目的清理.初始化.编译.测试.打包.集成测试.验证.部署和站点生成等几乎所有的构建步骤 3.Maven的生命周期是抽象的,这意味着生命周期本身不做任何实际的工作,实际的任务(如编译源代码)都是交由插件来完成的 Maven的这种思想与设计模式的模板方法非常相似 模板方法模式在父类中定义算法的整体结构,子类可以通过实现或者重写父类的方法来控制实际的行为,这样

Maven实战读书笔记(6)

Maven的坐标和依赖是?构件的逻辑表示方式和物理表示方式是? 1.坐标和依赖是任何一个构件在Maven世界中的逻辑表示方式 2.文件是Maven构件的物理表示方式 3.Maven通过仓库来统一管理这些文件 那么,构件是什么东东? 1.任何一个依赖.插件或者项目构建的输出,都可以称为构件 2.依赖log4j-1.2.15.jar是一个构件 3.插件maven-compiler-plugin-2.0.2.jar是一个构件 4.account-email项目构建完成后输出account-email-

Maven实战读书笔记(四):Maven生命周期与插件

Maven的生命周期是对所有构建过程的抽象和统一.包含了项目的清理.初始化.编译.测试.打包.集成测试.验证.部署和站点生成等几乎所有构建步骤. Maven的生命周期是抽象的,其实际行为是由插件来完成的,生命周期和插件两者协同合作,密不可分. 这种思想与设计模式中的模板方法非常相似.模板方法模式在父类定义算法的整体结构,子类通过实现或者重写父类的方法来控制实际行为,这样既能保证算法有足够的可扩展性,又能严格控制算法的整体结构. 4.1 生命周期 Maven拥有3套独立的生命周期:clean.de

Maven实战读书笔记(18)

代码行统计插件的POM <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <m

Maven实战读书笔记(七):Maven常用功能

7.1.资源排除 <resources> <!-- 启动过滤,包含的文件会被过滤掉 --> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> <includes> <include>src/main/resources/dev/*.*</include> <include

Maven实战读书笔记(3)

POM是什么? 1.像Make的Makefile.Ant的build.xml一样,Maven项目的核心是pom.xml 2.POM (Project Object Model, 项目对象模型) 定义了项目的基本信息,用于描述项目如何构建,声明项目依赖等等 如何编写一个Hello World的POM? 新建一个名为pom.xml的文件,输入内容如下: <?xml version="1.0" encoding="UTF-8"?> <project xm

Maven实战读书笔记(14)

什么是版本管理? 版本管理是指项目整体版本的演变过程管理,如从1.0-SNAPSHOT到1.0再到1.1-SNAPSHOT 什么是版本控制? 版本控制是指借助版本控制工具(如Subversion)追踪代码的每一个变更 什么时候可以将快照版本更新为发布版本 1.所有自动化测试应当全部通过 2.项目没有配置任何快照版本的依赖 3.项目没有配置任何快照版本的插件 4.项目所包含的代码已经全部提交到版本控制系统中 Maven的版本号定义约束 可能有个版本号是这样的,1.3.4-beta-2 Maven的

Maven实战读书笔记(7)

远程仓库的认证 1.一般来说,远程仓库无须认证就可以访问 2.但有时候出于安全考虑,需要提供认证信息,为了防止非法的仓库访问,管理员为每个仓库提供了一组用户名及密码 3.这时为了让Maven访问仓库内容,就需要配置认证信息 如何配置认证信息? 1.配置认证信息和配置仓库信息不同,仓库信息可以直接配置在POM文件中,但是认证信息必须配置在settings.xml文件中 2.这是因为POM往往是被提交到代码仓库中供所有成员访问的,而settings.xml一般只放在本机.因此,在settings.x

Maven实战读书笔记(15)

关于灵活的构建 一个优秀的构建系统必须足够灵活,它应该能够让项目在不同的环境下都能成功地构建. 例如,典型的项目都会有开发环境.测试环境和产品环境,这些环境的数据库配置不尽相同,那么项目构建的时候就需要能够识别所在的环境并使用正确的配置 还有一种常见的情况是,项目开发了大量的集成测试,这些测试运行起来非常耗时,不适合在每次构建项目的时候都运行,因此需要一种手段能让我们在特定的时候才激活这些集成测试,Maven为了支持构建的灵活性,内置了三大特性,即属性.Profile和资源过滤 Maven属性