maven内部运行原理解析(一)
来源于: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之间的关系:

到此为止,相信对于POM, pom.xml,Lifecycle, phase, goal这些概念应该十分清楚了。
maven内部运行原理解析(一)的更多相关文章
- maven内部运行原理解析
maven至今还是Java编程语言构建的事实标准,大部分项目还在使用maven来进行构建,因此了解maven内部运行的原理对定位和分析问题还是很有裨益的.本篇文章主要介绍一些maven内部运行过程中的 ...
- (转)Apache和Nginx运行原理解析
Apache和Nginx运行原理解析 原文:https://www.server110.com/nginx/201402/6543.html Web服务器 Web服务器也称为WWW(WORLD WID ...
- View Animation 运行原理解析
Android 平台目前提供了两大类动画,在 Android 3.0 之前,一大类是 View Animation,包括 Tween animation(补间动画),Frame animation(帧 ...
- JavaScript运行原理解析
原文:1.http://blog.csdn.net/liaodehong/article/details/50488098 2.Stack的三种含义 (阮一峰) 3. http://lib.csdn. ...
- .NET CORE学习笔记系列(5)——ASP.NET CORE的运行原理解析
一.概述 在ASP.NET Core之前,ASP.NET Framework应用程序由IIS加载.Web应用程序的入口点由InetMgr.exe创建并调用托管,初始化过程中触发HttpApplicat ...
- 转:Apache和Nginx运行原理解析
Web服务器 Web服务器也称为WWW(WORLD WIDE WEB)服务器,主要功能是提供网上信息浏览服务. 应用层使用HTTP协议. HTML文档格式. 浏览器统一资源定位器(URL). Web服 ...
- View 动画 Animation 运行原理解析
这次想来梳理一下 View 动画也就是补间动画(ScaleAnimation, AlphaAnimation, TranslationAnimation...)这些动画运行的流程解析.内容并不会去分析 ...
- Apache和Nginx运行原理解析
Web服务器 Web服务器也称为WWW(WORLD WIDE WEB)服务器,主要功能是提供网上信息浏览服务. 应用层使用HTTP协议. HTML文档格式. 浏览器统一资源定位器(URL). Web服 ...
- 转载-Apache和Nginx运行原理解析
本文只作为了解Apache和Nginx知识的一个梳理,想详细了解的请阅读文末参考链接中的博文. Web服务器 Web服务器也称为WWW(WORLD WIDE WEB)服务器,主要功能是提供网上信息浏览 ...
随机推荐
- 构建一个高可扩展性javabean和jsp连接数据库操作
1. 我们先在Tomcat 中创建一个DataSource- jdbc/Panabia,然后再创建一个java“基类”,这个类封装了数据库连接和连接的释放. package Panabia.db; i ...
- Excel向上取整
CEILING函数语法:CEILING(number,significance)
- java执行ping命令
public static void get() throws IOException{ String address="10.132.118.110"; Process proc ...
- 把NDK的工具链提取出来单独使用
独立toolchain 把NDK压缩包解压到系统,如/mnt目录下,后在/mnt目录下建立文件夹my_ndk_toolchain,然后再/mnt目录下执行以下命令:/mnt/android-ndk-r ...
- Composer使用体验
什么是Composer 简单来说,Composer是PHP的包依赖管理器.但是Composer并不是类似于Yum.Apt的包管理器.Composer可以用于包或者第三方库的安装,但是可以选择在Proj ...
- 深入理解Java中的组合和继承
Java是一个面向对象的语言.每一个学习过Java的人都知道,封装.继承.多态是面向对象的三个特征.每个人在刚刚学习继承的时候都会或多或少的有这样一个印象:继承可以帮助我实现类的复用.所以,很多开发人 ...
- 35个Jquery应用实例
Jquery库及相应插件如今红遍网络,收集了网络上有关JQuery的35个精彩使用例子,在此统一展示供JQuery使用时的查询. 1. 选择网页元素jQuery的基本设计和主要用法,就是" ...
- C语言:通过函数指针来完成两个数的加减乘除(函数指针当做参数使用)
// // main.c // Function_pointer // // Created by mac on 15/8/2. // Copyright (c) 2015年. All rig ...
- 服务 Service 清单文件中可设置的属性
PS:对于一个Service,在没有在AndroidManifest.xml中声明的情况下使用时,不会像Activity那样直接崩溃并提示找不到Activity. 对于显式Intent启动的Servi ...
- 比较windows phone 的回退事件与android的回退事件
public void onBackPressed() { finish(); } 如果要做一个页面导航的功能的话,就我而言,认为,windows phone开发比android更加人性化,更加傻瓜化 ...