Maven学习总结5 -- POM文件配置插件与依赖的引入

Maven 插件与依赖的引入

  • Maven 插件引入
      • 插件与插件的目标[mvn plugin_name:goal_name]
      • pluginManagement 与 plugins的意义与区别
  • Maven 依赖的引入
      • dependency 块中的元素列表(type,scope,exclusions,optional)解释
      • Maven依赖机制
          • 第一原则:短路径长度优先原则
          • 第二原则:先声明优先原则
      • dependencyManagement和dependencise的区别

Maven 插件引入

Maven 引入插件可以在POM文件中进行配置,在build标签中,通过pluginManagement ,plugins ,plugin标签来引入插件

<pluginManagement>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.pluginsgroupId>
            <artifactId>maven-source-pluginartifactId>
            <version>2.1version>
            <configuration>
                <attach>trueattach>
            configuration>
            <executions>
                <execution>
                    <phase>compilephase>
                    <goals>
                        <goal>jargoal>
                    goals>
                execution>
            executions>
        plugin>
    plugins>
pluginManagement>

除了必要的groupId,artifactId,version三个坐标系元素外(下称坐标系元素),我们还可以通过配置块configuration 和 执行块executions对单个插件进行进一步的配置,由于每一个插件的配置和执行块的配置不尽相同,这里就不做过多讨论。

插件与插件的目标[mvn plugin_name:goal_name]

一个插件可能具有多个目标项,例如 我们学习的maven的内置插件中的compiler插件,
compiler插件有两个目标,分别是compile 和testCompile,分别表示编译源代码 和 编译测试代码,

command

  • mvn compiler:compile
  • mvn compiler:testCompile

插件标签中,我们通常 通过configuration配置块 及 executions来对插件进行进一步的配置,每个目标可能具有单独的配置,甚至可能将插件的目标完全绑定到不同的阶段,以期在不同的阶段执行配置中的插件目标。
例如上例 中的配置, maven就会在phase(阶段)为compile(编译)的时候将源码打成jar包。

pluginManagement 与 plugins的意义与区别

我们在日常的开发中也许有注意到在有的pom文件中直接使用plugins包裹plugin进行插件的引入,而有的pom文件在plugins标签的外围还包裹pluginManagement 标签。那么两者之间有何区别呢?

简单来说:

  • pluginManagement 包裹的插件列表 仅表示 插件的声明和定义,Maven不会加载该插件;

  • 而plugins直接包裹的插件列表 则真实的引入了插件。

pluginManagement一般是用来在父POM中定义和配置插件,提供给子POM使用,子POM则使用plugins包围的plugin标签定义该标签,如果你在父POM中定义了版本之后,子模块中可以仅定义groupId和artifactId两个元素,而不用指定版本。这样做的好处是统一管理插件。

示例:
父级pom

<build>
    ...
	<pluginManagement>
      <plugins>
        <plugin>
          <groupId>org.apache.maven.pluginsgroupId>
          <artifactId>maven-jar-pluginartifactId>
          <version>2.6version>
          <executions>
            <execution>
              <id>pre-process-classesid>
              <phase>compilephase>
              <goals>
                <goal>jargoal>
              goals>
              <configuration>
                <classifier>pre-processclassifier>
              configuration>
            execution>
          executions>
        plugin>
      plugins>
	pluginManagement>
	...
build>

子级pom

<build>
    ...
    <plugins>
      <plugin>
        <groupId>org.apache.maven.pluginsgroupId>
        <artifactId>maven-jar-pluginartifactId>
      plugin>
    plugins>
    ...
build>

Maven 依赖的引入

maven通过pom文件实现项目之间的继承和单向依赖。

我们通常可以使用dependencyManagement 、dependencys、dependency三个标签来引入依赖。

<dependencies>
    <dependency>
      <groupId>junitgroupId>
      <artifactId>junitartifactId>
      <version>3.8.1version>
      <scope>testscope>
    dependency>

    <dependency>
      <groupId>org.mybatisgroupId>
      <artifactId>mybatisartifactId>
      <version>3.4.6version>
    dependency>
dependencies>

dependency 块中的元素列表(type,scope,exclusions,optional)解释

dependency 依赖块中包含多个子元素,除坐标系元素之外,这里仅学习一些常用的元素。

  • type:指定依赖类型,默认类型是jar。它通常表示依赖的文件的扩展名,
  • scope:表示项目将在哪个范围内引入该依赖。有五个范围可选:
    1. compile 默认的范围,用于编译,依赖可传播
    1. provided 类似于编译,但支持你期待jdk或者容器提供,类似于classpath ,依赖不可传播
    1. runtime 在执行时需要使用 依赖不可传播
    1. test 用于test任务时使用 依赖不可传播
    1. system 当scope为system时,表示该依赖项是我们自己提供的,不需要Maven到仓库里面去找。指定scope为system需要与另一个属性元素systemPath一起使用,它表示该依赖项在当前系统的位置,使用的是绝对路径。 依赖可传播
  • systemPath:仅用于范围为system。提供相应的路径,路径必须是绝对路径
  • exclusions:依赖排除,当计算传递依赖时, 从依赖构件列表里,列出被排除的依赖构件集。即告诉maven你只依赖指定的项目,不依赖项目的依赖。此元素主要用于解决版本冲突问题
  • optional:依赖仅在需要的时候被引入,是可选的,例如B依赖A ,C依赖B,那么在默认情况下C也依赖A,但如果B引入A依赖的时候设定optional == true , 则 C仅在 需要的情况下才会 依赖A。你可以把可选依赖理解为默认排除。用于连续依赖时使用。

Maven依赖机制

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

maven对于依赖相同的资源,默认会做出以下优化:

第一原则:短路径长度优先原则

例如,项目A有这样的依赖关系 : A–>B–>C–>X(1.0)、A–>D–>X(2.0),X是A的传递性依赖,但是两条依赖路径上有两个版 本的X,那么哪个X会被maven解析使用呢?两个版本都被解析显然是不对的,因为那会造成依赖重复,因此必须选择一个。maven依赖调解的第一原则:路径最近者优先。该例中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。那么到底谁会被解析使用呢?在maven2.0.8及之前的版本中,这是不确定的,但是maven2.0.9开始,为了尽可能避免构建的不确定性,maven定义了依赖调解的第二原则:第一声明者优先。在依赖路径长度相等的前提下,在POM中依赖声明的顺序决定了谁会被解析使用。顺序最靠前的那个依赖优胜。

dependencyManagement和dependencise的区别

这个区别于上文讲过的pluginManagement和plugins是非常相似的。

  • dependencyManagement块中依赖列表表示这些依赖的声明和定义,常在父pom文件中用于依赖版本的管理。该列表下的依赖并未实际引入,子类在继承父类的时候仍然需要使用dependencise块引入相应依赖,只是如果父pom中的dependencyManagement块中已经标注了该依赖的版本,那么子pom文件中仅需要标注groupId和artifactId两个属性的值即可引入该依赖,当然子pom文件也可以重写依赖的版本和定义。
  • dependencise块中依赖列表即表示这些依赖的声明,又表示这些依赖的实际引入。

你可能感兴趣的:(Devops,mvn,plugin,dependencies)