来源于:http://www.jianshu.com/p/0fb5e3fb704d

maven至今还是Java编程语言构建的事实标准,大部分项目还在使用maven来进行构建,因此了解maven内部运行的原理对定位和分析问题还是很有裨益的。本篇文章主要介绍一些maven内部运行过程中的一些基本概念,相信看完后,对那么些刚刚接触maven的读者来说maven将不再陌生。
  在具体分析项目构建的过程前,需要了解maven的一些基本概念,这些概念十分重要,请务必理解清楚后再看下文。基本概念主要有:POM,Lifecycle。这两个概念又会包含一些小的概念,下文会逐步讲解。
  POM: 注意这里的POM不是maven中构建过程使用的配置文件pom.xml,但他们之间还是有联系的。POM的全称是Project Object Model,用通俗点的话说就是对要构建的项目进行建模,将要构建的项目看成是一个对象(Object),后文就使用PO来指代这个对象。既然是一个对象,那么PO有哪些属性呢?在maven中一个项目都是用一个唯一的坐标(coordinate)来表示,坐标由groupId, artifactId, version, classifier, type这五部分组成。这样来说PO应该也要具备坐标属性。另外一方面,一个项目肯定不是孤立存在的,可能依赖于其他的一些项目,那么也就是说PO应该具备dependencies这个属性,用来表示其所依赖的外部项目。我们可以尝试一下用Java代码来描述下PO这个对象:

class PO{
private String groupId;
private String artifactId;
private String version;
private String classifier;
private String type;
private Set<PO> dependencies;
}

  我们知道XML的表达能力是很强大的,一个Java中的对象是可以用XML来描述,例如一个上面定义的PO对象则可以用下面的XML来描述(表达有不规范之处,理解其中的含义即可):

<PO>
<groupId></groupId>
<artifactId></artifactId>
<version></version>
<classifier><classifier>
<type></type>
<dependencies>
<PO></PO>
<PO></PO>
...
</dependencies>
</PO>

是不是好像和什么有点类似?对,就是pom.xml。pom.xml就是PO对象的XML描述。上面的PO定义还不完整,我们继续看下PO还有什么其他的属性。我们知道在Java中类是可以继承的,一个对象在创建的时候会同时创建其父类对象,类似的,PO对象也有其父对象,用parent属性来表示,并且PO对象会继承其父对象的所有属性。另外一方面,一个项目可能根据不同职责分为多个模块(module),所有模块其实也就是一个单独的项目,只不过这些项目会使用其父对象的一些属性来进行构建。我们将这些新的属性加到PO的定义中去:

class PO{
private String groupId;
private String artifactId;
private String version;
private String classifier;
private String type;
private Set<PO> dependencies;
private PO parent;
private Set<PO> modules;
}

再将这个定义用XML语言表示一下:

<PO>
<parent></parent>
<groupId></groupId>
<artifactId></artifactId>
<version></version>
<classifier><classifier>
<type></type>
<dependencies>
<PO></PO>
<PO></PO>
...
</dependencies>
<modules>
...
</modules>
</PO>

是不是越来越像pom.xml了?对,这就是pom.xml的由来。再说一遍:pom.xml就是PO对象的XML描述。到此为止,相信你再看pom.xml文件时,会有一个全新的认识。

  上面说的这些PO属性是项目的一些固有属性,到目前为止,我们还没有涉及项目的构建过程。构建过程对应的是PO对象的build属性,那么你应该马上想到,在pom.xml中就是<build>元素中的内容。这里就有引入maven中第二个核心概念:Lifecycle。Lifecycle直译过来就是生命周期。我们平常会接触到哪些周期呢?一年中春夏秋冬就是一个周期。一个周期中可能分为多个阶段,比如这里的春夏秋冬。在maven中一个构建过程就对应一个Lifecycle,这个Lifecycle也分为多个阶段,每个阶段叫做phase。你可能会问,那这个Lifecycle中包含多少个phase呢?一个标准的构建Lifecycle包含了如下的phase:

validate: 用于验证项目的有效性和其项目所需要的内容是否具备
initialize:初始化操作,比如创建一些构建所需要的目录等。
generate-sources:用于生成一些源代码,这些源代码在compile phase中需要使用到
process-sources:对源代码进行一些操作,例如过滤一些源代码
generate-resources:生成资源文件(这些文件将被包含在最后的输入文件中)
process-resources:对资源文件进行处理
compile:对源代码进行编译
process-classes:对编译生成的文件进行处理
generate-test-sources:生成测试用的源代码
process-test-sources:对生成的测试源代码进行处理
generate-test-resources:生成测试用的资源文件
process-test-resources:对测试用的资源文件进行处理
test-compile:对测试用的源代码进行编译
process-test-classes:对测试源代码编译后的文件进行处理
test:进行单元测试
prepare-package:打包前置操作
package:打包
pre-integration-test:集成测试前置操作
integration-test:集成测试
post-integration-test:集成测试后置操作
install:将打包产物安装到本地maven仓库
deploy:将打包产物安装到远程仓库

  在maven中,你执行任何一个phase时,maven会将其之前的phase都执行。例如 mvn install,那么maven会将deploy之外的所有phase按照他们出现的顺序一次执行。
  Lifecycle还牵涉到另外一个非常重要的概念:goal。注意上面Lifecycle的定义,也就是说maven为程序的构建定义了一套规范流程:第一步需要validate,第二步需要initialize... ... compile,test,package,... ... install,deploy,但是并没有定义每一个phase具体应该如何操作。这里的phase的作用有点类似于Java语言中的接口,只协商了一个契约,但并没有定义具体的动作。比如说compile这个phase定义了在构建流程中需要经过编译这个阶段,但没有定义应该怎么编译(编译的输入是什么?用什么编译javac/gcc?)。这里具体的动作就是由goal来定义,一个goal在maven中就是一个Mojo(Maven old java object)。Mojo抽象类中定义了一个execute()方法,一个goal的具体动作就是在execute()方法中实现。实现的Mojo类应该放在哪里呢?答案是maven plugin里,所谓的plugin其实也就是一个maven项目,只不过这个项目会引用maven的一些API,plugin项目也具备maven坐标。
  在执行具体的构建时,我们需要为lifecycle的每个phase都绑定一个goal,这样才能够在每个步骤执行一些具体的动作。比如在lifecycle中有个compile phase规定了构建的流程需要经过编译这个步骤,而maven-compile-plugin这个plugin有个compile goal就是用javac来将源文件编译为class文件的,我们需要做的就是将compile这个phase和maven-compile-plugin中的compile这个goal进行绑定,这样就可以实现Java源代码的编译了。有点绕,多看几遍。那么有人就会问,在哪里绑定呢?答案是在pom.xml<build>元素中配置即可。例如:

<build>
<plugins>
<plugin>
<artifactId>maven-myquery-plugin</artifactId>
<version>1.0</version>
<executions>
<execution>
<id>execution1</id>
<phase>test</phase>
<configuration>
<url>http://www.foo.com/query</url>
<timeout>10</timeout>
<options>
<option>one</option>
<option>two</option>
<option>three</option>
</options>
</configuration>
<goals>
<goal>query</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

就将maven-myquery-plugin中的query这个goal绑定到了test这个phase,后续在maven执行到test phase时就会执行query goal。还有有人可能会问,我都没有指定Java源文件的位置,编译啥?这就引出了maven的design principle。在maven中,有一个非常著名的principle就是convention over configuration(约定优于配置)。这一点和ant有非常大的区别,例如使用ant来进行编译时,我们需要指定源文件的位置,输出文件的位置,javac的位置,classpath... ...在maven中这些都是不需要,若没有手动配置,maven默认从<项目根目录>/src/main/java这个目录去查找Java源文件,编译后的class文件会保存在<项目根目录>/target/classes目录。在maven中,所有的PO都有一个根对象,就是Super POM。Super POM中定义了所有的默认的配置项。Super POM对应的pom.xml文件可以在maven安装目录下lib/maven-model-builder-3.0.3.jar:org/apache/maven/model/pom-4.0.0.xml中找到。用一张图来表示maven Lifecycle,phase,goal之间的关系:

Lifecyle-phase-plugin-goal关系图

到此为止,相信对于POM, pom.xml,Lifecycle, phase, goal这些概念应该十分清楚了。

maven内部运行原理解析(一)的更多相关文章

  1. maven内部运行原理解析

    maven至今还是Java编程语言构建的事实标准,大部分项目还在使用maven来进行构建,因此了解maven内部运行的原理对定位和分析问题还是很有裨益的.本篇文章主要介绍一些maven内部运行过程中的 ...

  2. (转)Apache和Nginx运行原理解析

    Apache和Nginx运行原理解析 原文:https://www.server110.com/nginx/201402/6543.html Web服务器 Web服务器也称为WWW(WORLD WID ...

  3. View Animation 运行原理解析

    Android 平台目前提供了两大类动画,在 Android 3.0 之前,一大类是 View Animation,包括 Tween animation(补间动画),Frame animation(帧 ...

  4. JavaScript运行原理解析

    原文:1.http://blog.csdn.net/liaodehong/article/details/50488098 2.Stack的三种含义 (阮一峰) 3. http://lib.csdn. ...

  5. .NET CORE学习笔记系列(5)——ASP.NET CORE的运行原理解析

    一.概述 在ASP.NET Core之前,ASP.NET Framework应用程序由IIS加载.Web应用程序的入口点由InetMgr.exe创建并调用托管,初始化过程中触发HttpApplicat ...

  6. 转:Apache和Nginx运行原理解析

    Web服务器 Web服务器也称为WWW(WORLD WIDE WEB)服务器,主要功能是提供网上信息浏览服务. 应用层使用HTTP协议. HTML文档格式. 浏览器统一资源定位器(URL). Web服 ...

  7. View 动画 Animation 运行原理解析

    这次想来梳理一下 View 动画也就是补间动画(ScaleAnimation, AlphaAnimation, TranslationAnimation...)这些动画运行的流程解析.内容并不会去分析 ...

  8. Apache和Nginx运行原理解析

    Web服务器 Web服务器也称为WWW(WORLD WIDE WEB)服务器,主要功能是提供网上信息浏览服务. 应用层使用HTTP协议. HTML文档格式. 浏览器统一资源定位器(URL). Web服 ...

  9. 转载-Apache和Nginx运行原理解析

    本文只作为了解Apache和Nginx知识的一个梳理,想详细了解的请阅读文末参考链接中的博文. Web服务器 Web服务器也称为WWW(WORLD WIDE WEB)服务器,主要功能是提供网上信息浏览 ...

随机推荐

  1. 构建一个高可扩展性javabean和jsp连接数据库操作

    1. 我们先在Tomcat 中创建一个DataSource- jdbc/Panabia,然后再创建一个java“基类”,这个类封装了数据库连接和连接的释放. package Panabia.db; i ...

  2. Excel向上取整

    CEILING函数语法:CEILING(number,significance)

  3. java执行ping命令

    public static void get() throws IOException{ String address="10.132.118.110"; Process proc ...

  4. 把NDK的工具链提取出来单独使用

    独立toolchain 把NDK压缩包解压到系统,如/mnt目录下,后在/mnt目录下建立文件夹my_ndk_toolchain,然后再/mnt目录下执行以下命令:/mnt/android-ndk-r ...

  5. Composer使用体验

    什么是Composer 简单来说,Composer是PHP的包依赖管理器.但是Composer并不是类似于Yum.Apt的包管理器.Composer可以用于包或者第三方库的安装,但是可以选择在Proj ...

  6. 深入理解Java中的组合和继承

    Java是一个面向对象的语言.每一个学习过Java的人都知道,封装.继承.多态是面向对象的三个特征.每个人在刚刚学习继承的时候都会或多或少的有这样一个印象:继承可以帮助我实现类的复用.所以,很多开发人 ...

  7. 35个Jquery应用实例

    Jquery库及相应插件如今红遍网络,收集了网络上有关JQuery的35个精彩使用例子,在此统一展示供JQuery使用时的查询.  1. 选择网页元素jQuery的基本设计和主要用法,就是" ...

  8. C语言:通过函数指针来完成两个数的加减乘除(函数指针当做参数使用)

    // //  main.c //  Function_pointer // //  Created by mac on 15/8/2. //  Copyright (c) 2015年. All rig ...

  9. 服务 Service 清单文件中可设置的属性

    PS:对于一个Service,在没有在AndroidManifest.xml中声明的情况下使用时,不会像Activity那样直接崩溃并提示找不到Activity. 对于显式Intent启动的Servi ...

  10. 比较windows phone 的回退事件与android的回退事件

    public void onBackPressed() { finish(); } 如果要做一个页面导航的功能的话,就我而言,认为,windows phone开发比android更加人性化,更加傻瓜化 ...