首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件开发 >

02 座标和依赖

2012-09-28 
02坐标和依赖一、坐标Maven中的坐标用来标识构件。Maven中的任意构件都有一个唯一的坐标,Maven可以通过这个

02 坐标和依赖

一、坐标
Maven中的坐标用来标识构件。Maven中的任意构件都有一个唯一的坐标,Maven可以通过这个坐标在仓库中查找相关构件,我们开发自己的项目时也需要一个坐标。
坐标由groupId、artifactid、version、packaging、classifier构成,如:

<groupId>org.sonatype.nexus</groupId><artifactId>nexus-indexer</artifactId><version>1.0.0</version><packaging>jar</packaging>

?

1.groupId:
????? 定义当前Maven项目隶属的实际项目。首先,Maven和实际的项目不是一定的一一对应的关系。比如SpringFramework这个开源项目,由多个Maven项目如:spring-core、spring-context等。其次,groupId不应该对应到项目隶属的组织或公司。因为一个组织很可能会有多个实际项目。最后,groupId和表示方式和Java包名的表示方式类似。通常是域的反写。

?

2.artifactId
???? 定义实际项目中的一个Maven项目(模块),推荐的做法是使用实际项目的名称作为artifactId的前缀。这样的好处是方便寻找。

?


3.version
???? 定义Maven项目当前所处的版本。

?

4.packaging:(可选)
???? 定义Maven项目的打包方式。首先,打包方式通常与生成构件的文件扩展名对象。如上例生成的文件名为nexus-indexer-1.0.0.jar。使用war打包方式最终会生成一个.war文件。但这个不是绝对的。其次,打包方式会影响到项目构建的生命周期。例如jar打包和war打包会使用不同的命令。最后,当不定义packaging时,默认是jar。

?

5.classifer:(不可直接定义)
????? 该元素用来定义主构建的一些附属属性。附属属性与主构件对应。如上例中的nexus-indexer-1.0.0.jar是主构件。该项目还有一些附属构件如:nexus-indexer-1.0.0-source.jar、nexus-indexer-1.0.0-javadoc.jar。这时source和javadoc就是这两个构件的classifier。
注意:不能直接定义项目的classifer,因为附属构件项目的直接默认生成的,而是由附加的插件帮助生成的。

?

?

二、依赖
??? 声明依赖使用pom.xml的project根元素下dependencies元素。如:

?

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

???? 每个dependencies可以包含任意个dependency元素,以声明一个一个依赖。每个依赖可用的属性有:
groupId、artifactId和version:依赖的基本坐标
type:依赖的类型,对应于项目坐标中的packaging。大部分情况下,该元素不必指定,其默认值是jar
scope:依赖范围
optional:标记依赖是否可选。
exclusions:用来排除传递性依赖。

?

?

三、依赖范围
????? 首先Maven在编译项目主代码时需要使用一套classpath;其实在编译的执行测试代码时会使用另一套classpath;最后,实际运行Maven项目时,又会使用一套classpath。
????? 依赖范围就是用来控制依赖与这三种classpath的关系。Maven有以下几种依赖范围:

compile:默认依赖范围。对于编译、测试和运行三种classpath都有效。?test:只对于测试classpath有效provided:只对编译和测试classpath有效,但在运行时无效。runtime:对于测试和运行classpath有效,但在编译主代码时无效。system:该依赖范围与三种classpath的关系和provided依赖范围完全一致。但是,使用system范围的依赖时,必须通过systemPath元素显式地指定依赖文件的路径。由于此类依赖不是通过Maven仓库获取的,而且往往与本机系统绑定,可能会造成不可移植,因此应该谨慎使用import:该依赖范围不会对三种classpath产生实际影响。在继承和依赖管理时再介绍。

?


四、传递性依赖
???? 假设A依赖于B,B依赖于C,C就是A的传递性依赖。B是A的第一直接依赖,C是B的第二直接依赖。
???? 依赖范围不仅可控制依赖与三种classpath的关系,还会对传递性依赖产生影响。 第一直接依赖和第二直接依赖的范围会影响传递性依赖的范围。
当第二直接依赖的范围是compile时,传递性依赖的范围与第一直接依赖的范围一致;
当第二直接依赖的范围是test的时候,依赖不会传递;
当第二直接依赖的范围是provided时,只传递第一直接依赖范围也为provided的依赖,且传递性依赖的范围同样为provided;
当第二直接依赖的范围是runtime时,传递性依赖的范围与第一直接依赖的范围一致,但compile除外,此时传递性依赖的范围为runtime。

?


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

例如,项目A的依赖关系为:A->B->C->X(1.0)、A->D->X(2.0)。X是A的传递性依赖,但是两条路径上的X版本不一致。
????? Maven的依赖调解第一原则是:路径最近者优先,第二原则是:第一声明者优先。

?


六、可选依赖
????? 在声明依赖时可使用<optional>true<optional>标准,这表明是可选依赖,它们只会对当前项目产生影响,其他项目依赖于B时候,这两个依赖不会被传递。如果真要使用这个依赖,需要在项目中直接声明。
理想情况下,是不应该使用可选依赖的,使用可靠依赖的原因是某一个项目实现了多个特性,依据单一职责原则,更好的做法是他建多个Maven项目,用户根据需要选择使用哪个Maven项目。

?


七、最佳实践
1.排除依赖
????? 传递性依赖简化项目依赖的管理的同时,也可能会带来一些问题。例如,第当前项目有一个第三方依赖,而这个第三方依赖由于某些原因依赖了另一个类库的SNAPSHOT版本,而SNAPSHOT是不稳定的版本。这里就需要排除掉该SHAPSHOT版本,并在当前项目中声明该类库的某个正式版本。还有一些情况,比如Sun JTA API等由于版权因素,我们希望使用其他版本实现来代替。这时就可以使用:

?

<dependency><exclusions><exclusion><groupId></groupId><artifactId></artifactId></exclusion></exclusions></dependency>

?

???? 排除依赖不需要指定版本号

?

2.归类依赖
????? 在我们一些框架如Spring FrameWork时,会有很多依赖,它们的版本号是相同的。这时我们可以声明一个变量,然后在其他地方使用这个变量 。
声明变量如下:

<project><properties><property><springframework.version>2.5.6</springframework.version></property></properties></project>

?

????? 使用方法如下:

<version>${springframework.version}</version>

?

?3.依赖分析优化
mvn dependency:list 查看解析后的最终依赖
mvn dependency:tree 查看解析后的依赖树
mvn dependency:analyze 帮助分析当前项目的依赖?
该命令的结果主要有两个部分:
首先是Used undeclared dependencies,指项目中使用到的,但是没有显式声明的依赖。
其次是Unused declared dependencies,指项目中未使用的显式依赖。

热点排行