当前位置: 首页 > news >正文

网站建设哪家便素材网站免费短视频

网站建设哪家便,素材网站免费短视频,服务器如何做网站,wordpress 开启注册Maven 坐标与依赖 1️⃣ 什么是Maven 坐标2️⃣ 坐标详解3️⃣ 依赖的配置4️⃣ 依赖范围5️⃣ 传递性依赖6️⃣ 依赖调解7️⃣ 可选依赖8️⃣ 最佳实践8.1 排除依赖8.2 归类依赖8.3 优化依赖 #x1f33e; 总结 正如前面文章所述#xff0c;Maven 的一大功能是管理项目依赖… Maven · 坐标与依赖 1️⃣ 什么是Maven 坐标2️⃣ 坐标详解3️⃣ 依赖的配置4️⃣ 依赖范围5️⃣ 传递性依赖6️⃣ 依赖调解7️⃣ 可选依赖8️⃣ 最佳实践8.1 排除依赖8.2 归类依赖8.3 优化依赖 总结 正如前面文章所述Maven 的一大功能是管理项目依赖。为了能自动化地解析任何一个 Java 构件 Maven 就必须将它们唯一标识这就依赖管理的底层基础——坐标。本节将详细分析 Maven 坐标的作用解释其每一个元素在此基础上再介绍如何配置Maven, 以及相关的经验和技巧以帮助我们管理项目依赖。 1️⃣ 什么是Maven 坐标 关于坐标 (Coordinate), 大家最熟悉的定义应该来自于平面几何。在一个平面坐标系中坐标 (x,y) 表示该平面上与x 轴距离为y, 与 y 轴距离为x 的一点任何一个坐标都能够唯一标识该平面中的一点。 在实际生活中我们也可以将地址看成是一种坐标。省、市、区、街道等一系列信息 同样可以唯一标识城市中的任一居住地址和工作地址。邮局和快递公司正是基于这样一种 坐标进行日常工作的。 对应于平面中的点和城市中的地址 Maven 的世界中拥有数量非常巨大的构件也就是平时用的一些jar、war等文件。在Maven 为这些构件引入坐标概念之前我们无法使用任何一种方式 来唯一标识所有这些构件。因此当需要用到 Spring Franework 依赖的时候大家会去 Spring Framework 网站寻找当需要用到 log4j 依赖的时候大家又会去 Apache 网站寻找。又因为各个项目的网站风格迥异大量的时间花费在了搜索、浏览网页等工作上面。 没有统一的规范、统一的法则该工作就无法自动化。重复地搜索、浏览网页和下载类似的 jar文件这本就应该交给机器来做。而机器工作必须基于预定义的规则 Maven 定义了这样一组规则世界上任何一个构件都可以使用Maven 坐标唯一标识 Maven 坐标的元素包括 groupld、artifactld、version、packaging、clasifer。现在只要我们提供正确的坐标元素 Maven 就能找到对应的构件。比如说当需要使用 Java5 平台上TestNG的5.8版本时就告诉 Maven: “groupld org.testng; artifactld testng; version5.8; classifier jdk15”, Maven 就会从仓库中寻找相应的构件供我们使用。 也许你会奇怪 “Maven 是从哪里下载构件的呢?” 答案其实很简单 Maven 内置了一个中央仓库的地址 (http://repol.maven.ong/maven2), 该中央仓库包含了世界上大部分流行的开源项目构件 Maven 会在需要的时候去那里下载。 在我们开发自己项目的时候也需要为其定义适当的坐标这是 Maven 强制要求的。 在这个基础上其他Maven 项目才能引用该项目生成的构件见下图。 2️⃣ 坐标详解 Maven 坐标为各种构件引入了秩序任何一个构件都必须明确定义自己的坐标而 一 组 Maven 坐标是通过一些元素定义的它们是 groupld、artifactld、version、packaging、classifier。先看一组坐标定义如下 groupIdorg.sonatype.nexus/groupId artifactIdnexus-indexer/artifactId version2.0.0Nersion packagingjarpackaging这是 nexus-indexer 的坐标定义 nexus-indexer 是一个对Maven 仓库编纂索引并提供搜索功能的类库它是 Nexus 项目的一个子模块。后面会详细介绍 Nexus。上述代码片段中其坐标分别为 groupld:org.sonatype.nexus、artifactld:nexus-indexer、version:2.0.0、packaging: jar, 没有 classifier。下面详细解释一下各个坐标元素 groupId定义当前 Maven 项目隶属的实际项目。首先 Maven 项目和实际项目不一定是一对一的关系。比如 Spring Framework 这一实际项目其对应的 Maven 项目会有很多如 spring-core、spring-context 等。这是由于Maven 中模块的概念因此一个实际项目往往会被划分成很多模块。其次 groupId不应该对应项目隶属的组织或公司。原因很简单一个组织下会有很多实际项目如果 groupId 只定义到组织级别 而后面我们会看到artifactId 只能定义Maven 项目(模块), 那么实际项目这个层将难以定义。最后 groupId 的表示方式与Java包名的表示方式类似通常与域名反向一一对应。上例中 groupId 为 org.sonatype.nexus, org.sonatype 表示 Sonatype 公司建立的一 个非盈利性组织nexus 表示 Nexus 这一实际项目该 groupId 与域名 nexus.sonatype.org 对应。artifactId该元素定义实际项目中的一个Maven项目(模块), 推荐的做法是使用实际项目名称作为 artifactId 的前缀。比如上例中的 artifactId 是 nexus-indexer, 使用了实际项目名 nexus 作为前缀这样做的好处是方便寻找实际构件。在默认情况下 Maven生成的构件其文件名会以 artifactId 作为开头如 nexus-indexer-2.0.0.jar, 使用实际项目名称作为前缀之后就能方便从一个 lib文件夹中找到某个项目的一组构件。考虑有5个项目每个项目都有一个 core模块如果没有前缀我们会看到很多 core-1.2.jar这样的文件加上实际项目名前缀之后便能很容易区分 foo-core-1.2.jar、bar-core-1.2.jar … … 。version该元素定义Maven 项目当前所处的版本如上例中 nexus-indexer 的版本是 2.0.0。需要注意的是 Maven 定义了一套完整的版本规范以及快照 (SNAPSHOT)的概念。后面文章会详细讨论版本管理内容。packaging该元素定义 Maven 项目的打包方式。首先打包方式通常与所生成构件的文件扩展名对应 如上例中 packaging 为 jar, 最终文件名为 nexus-indexer-2.0.0.jar, 而使用 war 打包方式的Maven 项目最终生成的构件会有一个 .war 文件 不过这不是绝对的。其次打包方式会影响到构建的生命周期比如 jar打包和 war打包会使用不同的命令。最后当不定义 packaging 的时候Maven 会使用默认值 jar。classifier该元素用来帮助定义构建输出的一些附属构件。附属构件与主构件对应 如上例中的主构件是 nexus-indexer-2.0.0.jar, 该项目可能还会通过使用一些插件生成如nexus-indexer-2.0.0-javadoc.jar、nexus-indexer-2.0.0-sources. jar 这样一些附属构件其包含了Java 文档和源代码。这时候 javadoc和 sources 就是这两个附属构件的classifier。这样附属构件也就拥有了自己唯一的坐标。还有一个关于classifier 的典型例子是 TestNG, TestNG 的主构件是基于Java 1.4平台的而它又提供了一个classifier为 jdk5 的附属构件。注意不能直接定义项目的 classifier, 因为附属构件不是项目直接默认生成的而是由附加的插件帮助生成。 上述5个元素中 groupId、artifactId、version 是必须定义的 packaging是可选的(默认为jar), 而 classifier是不能直接定义的。 同时项目构件的文件名是与坐标相对应的 一般的规则为 artifactId-version [-classifier].packaging, [-classifier] 表示可选。比如上例 nexus-indexer 的主构件为 nexus-indexer-2.0.0.jar, 附属构件有 nexus-indexer-2.0.0-javadoe.jar。这里还要强调的一点是packaging 并非一定与构件扩展名对应比如 packaging 为 maven-plugin 的构件扩展名为 jar。 此外 Maven 仓库的布局也是基于Maven 坐标这一点会在介绍 Maven 仓库的时候详细解释。理解清楚城市中地址的定义方式后邮递员就能够开始工作了同样地理解清楚 Maven 坐标之后我们就能开始讨论Maven 的依赖管理了。 3️⃣ 依赖的配置 上面介绍了maven配置文件中一些简单的依赖配置可以看到依赖会有基本的 groupId、artifactId 和 version 等元素组成。其实一个依赖声明还可以包含如下的一些元素 project...dependenciesdependencygroupId.../groupIdartifactId.../artifactIdversion.../versiontype.../typescope.../scopeoptional.../optionalexclusionsexclusion.../exclusion/exclusions/dependency/dependencies... /project根元素 project 下的 dependencies 可以包含一个或者多个 dependency 元素以声明一个或者多个项目依赖。每个依赖可以包含的元素有 groupId 、artifactId 和 version依赖的基本坐标对于任何一个依赖来说基本坐标是最重要的 Maven 根据坐标才能找到需要的依赖。type依赖的类型对应于项目坐标定义的 packaging 。大部分情况下该元素不必声明其默认值为jar。scope依赖的范围后面会详细介绍。optional标记依赖是否可选后面会详细介绍。exclusions用来排除传递性依赖后面会详细介绍。 大部分依赖声明只包含基本坐标然而在一些特殊情况下其他元素至关重要。后面会对它们的原理和使用方式详细介绍。 4️⃣ 依赖范围 本节将详细解释什么是依赖范围以及各种依赖范围的效果和用途。 首先需要知道 Maven 在编译项目主代码的时候需要使用一套 classpath。 在上例中编译项目主代码的时候需要用到 sping-core, 该文件以依赖的方式被引入到 classpath中。其次 Maven 在编译和执行测试的时候会使用另外一套 classpath。最后实际运行Maven 项目的时候又会使用一套 classpath, 上例中的 spring-core 需要在该classpath 中而JUnit 则不需要。 依赖范围就是用来控制依赖与这三种 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 驱动。 system系统依赖范围。该依赖与三种 classpath 的关系和 provided 依赖范围完全一致。但是使用system 范围的依赖时必须通过systemPath 元素显式地指定依赖文件 的路径。由于此类依赖不是通过Maven 仓库解析的而且往往与本机系统绑定可能造成构建的不可移植因此应该谨慎使用。 systemPath 元素可以引用环境变量如 dependencygroupIdjavax.sql/groupIdartifactIdjdbc-stdext/artifactIdversion2.0/versionscopesystem/scopesystemPath${java.home}/lib/rt.jar/systemPath /dependencyimport(Maven 2.0.9及以上)导入依赖范围。该依赖范围不会对三种 classpath 产生实际的影响在后续介绍 Maven 依赖和 dependeneyManagement 的时候会详细介绍此依赖范围。 上述除 import 以外的各种依赖范围与三种 classpath的关系如下所示。 依赖范围Scope对于编译classpath有效对于测试classpath有效对于运行时classpath有效例子compile✔️✔️✔️spring-coretest-✔️-Junitprovided✔️✔️-servlet-apiruntime-✔️✔️JDBC驱动system✔️✔️-本地的 maven仓库之外的类库文件 5️⃣ 传递性依赖 考虑一个基于Spring Framework 的项目如果不使用Maven, 那么在项目中就需要手动 下载相关依赖。由于Spring Framework 又会依赖于其他开源类库因此实际中往往会下载一个很大的如 spring-framework-2.5.6-with-dependencies.zip 的包这里包含了所有Spring Framework 的 jar包以及所有它依赖的其他 jar包。这么做往往就引入了很多不必要的依赖。 另一种做法是只下载 spring-framework-2.5.6.zip 这样一个包这里不包含其他相关依赖到实际使用的时候再根据出错信息或者查询相关文档加入需要的其他依赖。很显然这也是一件非常麻烦的事情。 Maven 的传递性依赖机制可以很好地解决这一问题。例如现在有一个名为 account-email 的项目该项目有一个 org.springframework:spring-core:2.5.6 的依赖而实际上 spring-core 也有它自己的依赖我们可以直接访问位于中央仓库的该构件的POM: http://repol.maven.org/maven2/org/springframework/spring-core/2.5.6/spring-core-2.5.6.pom。该文件包含了一个commons-logging 依赖如下。 dependencygroupIdcommons-logging/groupIdartifactIdcommons-logging/artifactIdversion1.1.1/version /dependency该依赖没有声明依赖范围那么其依赖范围就是默认的compile。 同时回顾—下 account-email, spring-core 的依赖范围也是 compile。 account-mail 有一个compile 范围的 spring-core 依赖 sping-core 有一个 compile 范围的 commons-logging 依赖那么 commons-logging 就会成为 account-email 的 compile 范围依赖 commons-logging 是 account-email 的一个传递性依赖如下图所示。 有了传递性依赖机制在使用Spring Framework 的时候就不用去考虑它依赖了什么也 不用担心引入多余的依赖。 Maven 会解析各个直接依赖的 POM, 将那些必要的间接依赖 以传递性依赖的形式引入到当前的项目中。 依赖范围不仅可以控制依赖与三种 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 是传递性依赖。第一直接依赖的范围和第二直接依赖的范围决定了传递性依赖的范围如下表所示最左边一列表示第一直接依赖范围最上面一行表示第二直接依赖范围中间的交叉单元格则表示传递性依赖范围。 compiletestprovidedruntimecompilecompile--runtimetesttest--testprovidedprovided-providedprovidedruntimeruntime--runtime 为了能帮助大家更好地理解上表再举个例子。 account-email 项目有一个 com.icegreen:greenmail:1.3.1b 的直接依赖我们说这是第一直接依赖其依赖范围是test; 而 greenmail又有一个 javax.mail:mail:1.4 的直接依赖我们说这是第二直接依赖其依赖范围是 compile。 显然 javax.mail:mail:1.4 是 account-email 的传递性依赖对照上表可以知道当第一直接依赖范围为test, 第二直接依赖范围是 compile 的时候传递性依赖的范围是test, 因此 javax.mail:mail:1.4 是 account-email 的一个范围是 test的传递性依赖。 仔细观察一下上表,可以发现这样的规律当第二直接依赖的范围是 compile 的时候传递性依赖的范围与第一直接依赖的范围一致当第二直接依赖的范围是 test 的时候 依赖不会得以传递当第二直接依赖的范围是 provided 的时候只传递第一直接依赖范围 也为provided 的依赖且传递性依赖的范围同样为 provided; 当第二直接依赖的范围是runtime 的时候传递性依赖的范围与第一直接依赖的范围一致但 compile 例外此时传递性依赖的范围为 runtime。 6️⃣ 依赖调解 Maven 引入的传递性依赖机制 一方面大大简化和方便了依赖声明另一方面大部 分情况下我们只需要关心项目的直接依赖是什么而不用考虑这些直接依赖会引入什么传递性依赖。但有时候当传递性依赖造成问题的时候我们就需要清楚地知道该传递性依赖是从哪条依赖路径引入的。 例如项目A 有这样的依赖关系 A-B-C-X(1.0)、A-D-X(2.0), X 是 A 的传递性依赖但是两条依赖路径上有两个版本的X, 那么哪个X 会被 Maven 解析使用呢? 两个版本都被解析显然是不对的因为那会造成依赖重复因此必须选择一个。Maven 依赖调解 (Dependency Mediation) 的第一原则是路径最近者优先。该例中X(1.0) 的路径长度为 3 , 而 X(2.0) 的路径长度为2, 因此X(2.0) 会被解析使用。 依赖调解第一原则不能解决所有问题比如这样的依赖关系 A-B-Y(1.0)、A- C-Y(2.0), Y(1.0) 和 Y(2.0) 的依赖路径长度是一样的都为2。那么到底谁会被解析 使用呢? 在Maven 2.0.8及之前的版本中这是不确定的但是从 Maven 2.0.9开始为了尽可能避免构建的不确定性 Maven 定义了依赖调解的第二原则第一声明者优先。 在依赖路径长度相等的前提下在POM 中依赖声明的顺序决定了谁会被解析使用顺序最靠前的那个依赖优胜。该例中如果B 的依赖声明在C 之前那么Y(1.0) 就会被解析使用。 7️⃣ 可选依赖 假设有这样一个依赖关系项目A 依赖于项目B, 项目B 依赖于项目X 和Y, B 对于X 和Y 的依赖都是可选依赖A-B、B-X(可选)、B-Y(可选)。根据传递性依赖的定义如果所有这三个依赖的范围都是 compile, 那么 X、Y 就是A 的 compile 范围传递性依赖。然而由于这里X、Y 是可选依赖依赖将不会得以传递。换句话说 X、Y 将不会对 A有任何影响如下图所示。 为什么要使用可选依赖这一特性呢? 可能项目B 实现了两个特性其中的特性一依赖于X, 特性二依赖于Y, 而且这两个特性是互斥的用户不可能同时使用两个特性。比如 B 是一个持久层隔离工具包它支持多种数据库包括 MySQL、PostgreSQL 等在构建这个 工具包的时候需要这两种数据库的驱动程序但在使用这个工具包的时候只会依赖一种数据库。 项目B 的依赖声明见下边代码清单。 projectmodelVersion4.0.0/modelVersiongroupIdcom.xiaoshan.mvnbook/groupId artifactIdproject-b/artifactIdversion1.0.0/versiondependenciesdependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactId version5.1.10/versionoptionaltrue/optional/dependencydependencygroupIdpostgresql/groupIdartifactIdpostgresql/artifactIdversion8.4-701.jdbc3/versionoptionaltrue/optional/dependency/dependencies /project上述 XML代码片段中使用optional元素表示 mysql-connector-java 和 postgresql 这两个依赖为可选依赖它们只会对当前项目B产生影响当其他项目依赖于B的时候这两个依赖不会被传递。因此当项目A依赖于项目B的时候如果其实际使用基于MySQL数据库那么在项目A中就需要显式地声明 mysgl-connectorjava这一依赖见以下代码清单。 projectmodelVersion4.0.0/modelVersiongroupIdcom.xiaoshan.mvnbook/groupIdartifactIdproject-a/artifactIdversion1.0.0/versiondependenciesdependencygroupIdcom.xiaoshan.mvnbook/groupIdartifactIdproject-b/artifactIdversion1.0.0/version/dependencydependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdversion5.1.10/version/dependency/dependencies /project最后关于可选依赖需要说明的一点是在理想的情况下是不应该使用可选依赖的。 前面我们可以看到使用可选依赖的原因是某一个项目实现了多个特性在面向对象设计中有个单一职责性原则意指一个类应该只有一项职责而不是糅合太多的功能。 这个原则在规划 Maven 项目的时候也同样适用。在上面的例子中更好的做法是为MySQL 和 PostgreSQL分别创建一个 Maven 项目 基于同样的 groupId 分配不同的artifactId, 如 com.xiaoshan. mvnbook:project-b-mysql 和 com.xiaoshan. mvnbook:project-b-postgresgl, 在各自的 POM 中声明对应的JDBC 驱动依赖而且不使用可选依赖用户则根据需要选择使用 pro-ject-b-mysql 或者 project-b-postgresql。 由于传递性依赖的作用就不用再声明JDBC 驱动依赖。 8️⃣ 最佳实践 Maven 依赖涉及的知识点比较多在理解了主要的功能和原理之后最需要的当然就是前人的经验总结了我们称之为最佳实践。本小节归纳了一些使用Maven 依赖常见的技 巧方便用来避免和处理很多常见的问题。 8.1 排除依赖 传递性依赖会给项目隐式地引入很多依赖这极大地简化了项目依赖的管理但是有些时候这种特性也会带来问题。例如当前项目有一个第三方依赖而这个第三方依赖由于某些原因依赖了另外一个类库的SNAPSHOT 版本那么这个 SNAPSHOT 就会成为当前项目的传递性依赖而 SNAPSHOT 的不稳定性会直接影响到当前的项目。这时就需要排除掉该SNAPSHOT, 并且在当前项目中声明该类库的某个正式发布的版本。还有 一些情况你可能也想要替换某个传递性依赖比如 Sun JTA API, Hibernate 依赖于这个JAR, 但是由于版权的因素该类库不在中央仓库中而 Apache Geronimo项目有一个对应的实现。这时你就可以排除 Sun JAT API, 再声明 Geronimo 的 JTA API实现见如下代码清单。 projectmodelVersion4.0.0/modelVersiongroupIdcom.xiaoshan.mvnbook/groupIdartifactIdproject-a/artifactIdversion1.0.0/versiondependenciesdependencygroupIdcom.xiaoshan.mvnbook/groupIdartifactIdproject-b/artifactIdversion1.0.0/versionexclusionsexclusiongroupIdcom.xiaoshan.mvnbook/groupIdartifactIdproject-c/artifactId/exclusion/exclusions/dependencydependencygroupIdcom.xiaoshan.mvnbook/groupIdartifactIdproject-c/artifactIdversion1.1.0/version/dependency/dependencies /project 上述代码中项目A依赖于项目B, 但是由于一些原因不想引入传递性依赖C, 而是自己显式地声明对于项目C 1.1.0版本的依赖。代码中使用 exclusions 元素声明排除依赖exclusions 可以包含一个或者多个exclusion子元素因此可以排除一个或者多个传递性依赖。需要注意的是声明 exclusion 的时候只需要 groupId 和 artifactId,而不需要version元素这是因为只需要 groupId 和 artifactId就能唯一定位依赖图中的某个依赖。换句话说Maven解析后的依赖中不可能出现 groupId 和artifactId相同但是version不同的两个依赖。该例的依赖解析逻辑如下图所示。 8.2 归类依赖 在前面文章中介绍过在一个项目中可能有很多关于 Spring Framework 的依赖它们分别是 org.springframework:spring-core:2.5.6、org.springframework:spring-beans:2.5.6、org.springframework:spring-context:2.5.6 和 org.springframework:spring-context-support:2.5.6, 它们是来自同一项目的不同模块。 因此所有这些依赖的版本都是相同的而且可以预见如果将来需要升级SpringFramework, 这些依赖的版本会一起升级。这一情况在Java中似曾相识考虑如下简单代码。 public double c(double r){return 2 * 3.14 * r; }public double s(double r){return 3. 14 * r * r; } 这两个简单的方程式计算圆的周长和面积稍微有经验的程序员一眼就会看出一个问题使用字面量(3.14)显然不合适应该使用定义一个常量并在方法中使用见如下代码清单。 public final double PI 3.14;public double c(double r){return 2 * PI * r; }public double s(double r){return PI * r * r; } 使用常量不仅让代码变得更加简洁更重要的是可以避免重复在需要更改 PI的值的 时候只需要修改一处降低了错误发生的概率。 同理对于account-email 中这些SpringFramework来说也应该在一个唯一的地方定义 版本并且在dependency声明中引用这一版本。这样在升级SpringFramework的时候就只需要修改一处实现方式见如下代码清单。 projectmodelVersion4.0.0/modelVersiongroupIdcom.xiaoshan.mvnbook.account/groupIdartifactIdyaccount-email/artifactIdnameAccountEmail/nameversion1.0.0-SNAPSHOT/versionpropertiesspringframework.version2.5.6/springframework.version/propertiesdependenciesdependencygroupIdorg.springframework/groupIdartifactIdspring-core/artifactIdversion${springframework.version}/version/dependencydependencygroupIdorg.springframework/groupIdartifactIdspring-beans/artifactIdversion${springframework.version}/version/dependencydependencygroupIdorg.springframework/groupIdartifactIdspring-context/artifactIdsversion${springframework.version}/version/dependencydependencygroupIdorg.springframework/groupIdartifactIdspring-context-support/artifactIdversion${springframework.version}/version/dependency/dependencies /project 这里简单用到了Maven 属性(后面文章会详细介绍 Maven 属性) , 首先使用 properties 元 素定义Maven 属性该例中定义了一个 springframework. version 子元素其值为 2.5.6。有了这个属性定义之后 Maven 运行的时候会将 POM 中的所有的 ${springframework.version} 替换成实际值 2.5.6。也就是说可以使用美元符号$和大括弧 {和}环绕的方式引用 Maven 属性。然后将所有 Spring Framework 依赖的版本值用这一属性引用表示。这和在Java 中用常量 PI 替换 3.14 是同样的道理不同的只是语法。 8.3 优化依赖 在软件开发过程中程序员会通过重构等方式不断地优化自己的代码使其变得更简 洁、更灵活。同理程序员也应该能够对Maven 项目的依赖了然于胸并对其进行优化 如去除多余的依赖显式地声明某些必要的依赖。 本文前面的内容已经介绍到 Maven 会自动解析所有项目的直接依赖和传递性依赖并且根据规则正确判断每个依赖的范围对于一些依赖冲突也能进行调节以确保任何一个构件只有唯一的版本在依赖中存在。在这些工作之后最后得到的那些依赖被称为已解析依赖(Resolved Dependency)。 可以运行如下的命令查看当前项目的已解析依赖 mvn dependency:list在项目中执行该命令结果如图所示。 上图显示了所有 account-email 的已解析依赖同时每个依赖的范围也得以明确标示。 在此基础上还能进一步了解已解析依赖的信息。将直接在当前项目POM 声明的依赖 定义为顶层依赖而这些顶层依赖的依赖则定义为第二层依赖以此类推有第三、第四层依赖。当这些依赖经 Maven 解析后就会构成一个依赖树通过这棵依赖树就能很清楚地看到某个依赖是通过哪条传递路径引入的。可以运行如下命令查看当前项目的依赖树 mvn dependency:tree在项目中执行该命令效果如下图所示。 从图中能够看到虽然我们没有声明 org.sl4j:sl4j-api:1.3 这一依赖但它还是经过 com.icegreen:greenmail:1.3 成为了当前项目的传递性依赖而且其范围是 test。 使用 dependency:list 和 dependeney:tree 可以帮助我们详细了解项目中所有依赖的具体 信息在此基础上还有 dependency:analyze 工具可以帮助分析当前项目的依赖。 为了说明该工具的用途先将 spring-context 这一依赖删除然后构建项目你会发现编译、测试和打包都不会有任何问题。通过分析依赖树可以看到 spring-context是 spring-context-support 的依赖因此会得以传递到项目的 classpath 中。现在再运行如下命令 mvn dependency:analyze结果如下图所示。 该结果中重要的是两个部分。首先是Used undeclared dependencies, 意指项目中使用到的但是没有显式声明的依赖这里是 spring-context。 这种依赖意味着潜在的风险当前项目直接在使用它们例如有很多相关的Java import 声明而这种依赖是通过直接依赖传递进来的当升级直接依赖的时候相关传递性依赖的版本也可能发生变化这种变化不易察觉但是有可能导致当前项目出错。例如由于接口的改变当前项目中的相关代码无法编译。这种隐藏的、潜在的威胁一旦出现就往往需要耗费大量的时间来查明真相。因此 显式声明任何项目中直接用到的依赖。 结果中还有一个重要的部分是 Unused declared dependencies, 意指项目中未使用的但 显式声明的依赖这里有 spring-core 和 spring-beans、 需要注意的是 对于这样一类依赖 我们不应该简单地直接删除其声明而是应该仔细分析。由于dependeney:analyze 只会分析编译主代码和测试代码需要用到的依赖, 一些执行测试和运行时需要的依赖它就发现不了。 很显然该例中的 spring-core 和 spring-beans 是 运 行 Spring Framework 项目必要的类库因此不应该删除依赖声明。当然有时候确实能通过该信息找到一些没用的依赖但一定要小心测试。 总结 本文主要介绍了Maven 的两个核心概念坐标和依赖。解释了坐标的由来并详细阐述了各坐标元素的作用及定义方式。随后引入了一个项目实际的基于 Spring Framework 的模块包括了POM 定义、业务代码和测试代码。在这一直观感受的基础上再花篇幅介绍了 Maven 依赖包括依赖范围、传递性依赖、可选依赖等概念。最后当然少不了关于依赖的一些最佳实践。通过阅读本文大家应该已经能够透彻地了解 Maven 的依赖管理机制。下一节将会介绍 Maven 的另一个核心概念仓库。 ⏪ 温习回顾上一篇点击跳转 《【Maven教程】三基础使用篇入门使用指南——POM编写、业务代码、测试代码、打包与运行、使用Archetype生成项目骨架~》 ⏩ 继续阅读下一篇点击跳转 《【Maven教程】五》
http://www.w-s-a.com/news/287554/

相关文章:

  • 甘肃网站建设制作商网站空间哪家公司的好
  • 思途旅游网站建设系统用vscode做网站
  • 广州站改造最新消息半年工作总结ppt模板
  • logo模板下载网站推荐哪家网站开发培训好
  • 做外贸网站效果图页面关键词优化
  • 广平网站建设成都活动轨迹
  • 小型网站网站建设需要网络公司是什么行业
  • 滑动 手机网站 代码网页制作与设计讨论
  • 自己做网站处理图片用什么软件wordpress html5支持
  • 校园网站怎么建软文文案范文
  • 中国建设官方网站如何创建自己的软件
  • 来宾住房与城乡建设网站天津西青区怎么样
  • 西安网站建设培训班鄂州网页定制
  • 西部数码网站备份自己怎么做网站啊
  • h5网站开发用什么软件制作公司网站建设代理怎么做
  • 网站建设资料准备网上购物app有哪些
  • 沧州做网站优化哪家公司便宜国内百度云网站建设
  • 网站的最近浏览 怎么做龙岩市人才网最新招聘信息
  • 网站建设需要找工信部吗网站开发账务处理
  • 做那种的视频网站个体工商网站备案
  • 推广网官方推广网站中国建设招聘信息网站
  • 医院网站建设需要多少钱网络营销渠道可分为哪几种
  • 怎么取网页视频网站元素计算机专业论文网站开发
  • 上海网站建设备案号怎么恢复wordpress打开页面空白
  • 30个做设计的网站企业设计网站
  • 招生网站开发的背景创意 wordpress
  • 网站备案资料查询小型企业管理系统软件
  • 温州网站建设维护怎么做好网站开发、设计
  • 佛山 做网站公司有哪些网站排名忽然不见了
  • 广告网站建设最专业东莞大朗网站设计