生命周期

生命周期

Maven对构建(build)的过程进行了抽象和定义,这个过程被称为构建的生命周期(lifecycle)。生命周期(lifecycle)由多个阶段(phase)组成,每个阶段(phase)会挂接一到多个goalgoalmaven里定义任务的最小单元,相当于ant里的target

Maven的生命周期就是对所有的构建过程进行抽象和统一。包含了项目的清理、初始化、编译、测试、打包、集成测试、验证、部署和站点生成等几乎所有的构建步骤。Maven的生命周期是抽象的,即生命周期不做任何实际的工作,实际任务由插件完成,类似于设计模式中的模板方法。

核心概念

  • lifecycle:生命周期,这是maven最高级别的的控制单元,它是一系列的phase组成,也就是说,一个生命周期,就是一个大任务的总称,不管它里面分成多少个子任务,反正就是运行一个lifecycle,就是交待了一个任务,运行完后,就得到了一个结果,中间的过程,是phase完成的,自己可以定义自己的lifecycle,包含自己想要的phase

  • phase:可以理解为任务单元,lifecycle是总任务,phase就是总任务分出来的一个个子任务,但是这些子任务是被规格化的,它可以同时被多个lifecycle所包含,一个lifecycle可以包含任意个phasephase的执行是按顺序的,一个phase可以绑定很多个goal,至少为一个,没有goalphase是没有意义的。

  • goal:这是执行任务的最小单元,它可以绑定到任意个phase中,一个phase有一个或多个goalgoal也是按顺序执行的,一个phase被执行时,绑定到phase里的goal会按绑定的时间被顺序执行,不管phase己经绑定了多少个goal,你自己定义的goal都可以继续绑到phase中。

  • mojo: lifecyclephasegoal都是概念上的东西,mojo才是做具体事情的,可以简单理解mojogoal的实现类,它继承于AbstractMojo,有一个execute方法,goal等的定义都是通过在mojo里定义一些注释的anotation来实现的,maven会在打包时,自动根据这些anotation生成一些xml文件,放在pluginjar包里。

抛开mojo不讲,lifecyclephasegoal就是级别的大小问题,引用必须是从高级引用下级(goal绑定到phase,也可理间为phase引用goal,只是在具体绑定时,不会phase定义引用哪些goal,但是执行是,却是phase调用绑定到它那的goal,也不能跨级引用,如lifecycle可以引用任意的phase,不同lifecycle可以同时引用相同的phaselifecycle不能跨级引用goalgoal会绑定到任意的phase中,也就是说不同的phase可以同时引用相同的goal,所以goal可以在一个lifecycle里被重复执行哦,goal自然也不能说绑定到lifecycle中,它们三者的关系可以用公司里的 总领导,组领导,与职员的关系来解释。

lifecyclephase执行会指向之前所有的phase,然后执行当前指定的phase,一个phase会引用至少一个goalplugin中的goal只是单单执行当前指定的goal。执行install:install只会执行installplugin中的goal:install,但是项目创建后还没有进行之前必要的步骤,比如complie。这样直接执行install:install是肯定会出错的。

三套生命周期

Maven有三套相互独立的生命周期,分别是cleandefaultsite。每个生命周期包含一些阶段(phase,阶段是有顺序的,后面的阶段依赖于前面的阶段。

  • clean生命周期:清理项目,包含三个phase

1)pre-clean:执行清理前需要完成的工作 2)clean:清理上一次构建生成的文件 3)post-clean:执行清理后需要完成的工作

  • default生命周期:构建项目,重要的phase如下:

1)validate:验证工程是否正确,所有需要的资源是否可用。 2)compile:编译项目的源代码。 3)test:使用合适的单元测试框架来测试已编译的源代码。这些测试不需要已打包和布署。 4)package:把已编译的代码打包成可发布的格式,比如jar。 5)integration-test:如有需要,将包处理和发布到一个能够进行集成测试的环境。 6)verify:运行所有检查,验证包是否有效且达到质量标准。 7)install:把包安装到maven本地仓库,可以被其他工程作为依赖来使用。 8)deploy:在集成或者发布环境下执行,将最终版本的包拷贝到远程的repository,使得其他的开发者或者工程可以共享。

  • site生命周期:建立和发布项目站点,phase如下:

1)pre-site:生成项目站点之前需要完成的工作 2)site:生成项目站点文档 3)post-site:生成项目站点之后需要完成的工作 4)site-deploy:将项目站点发布到服务器

各个生命周期相互独立,一个生命周期的阶段前后依赖。举例如下:

  • mvn clean:调用clean生命周期的clean阶段,实际执行pre-cleanclean阶段

  • mvn test:调用default生命周期的test阶段,实际执行test以及之前所有阶段

  • mvn clean install:调用clean生命周期的clean阶段和defaultinstall阶段,实际执行pre-cleancleaninstall以及之前所有阶段

Mojo

phase为目标构建

phase为目标进行构建是最常见的,如我们平时经常执行的mvn compile,mvn test,mvn package… 等等,compile,test,package都是maven生命周期(lifecycle)里的phase,通过mvn命令,你可以指定一次构建执行到那一个阶段,在执行过程中,所有经历的执行阶段(phase)上绑定的goal都将得到执行。例如,对于一个jar包应用,当执行mvn package命令时,mavenvalidate阶段一个阶段一个阶段的执行,在执行到compile阶段时,compiler插件的compile goal会被执行,因为这个goal是绑定在compile阶段(phase)上的。这一点可从其对应的mojo类上得知:

CompilerMojo

再比如经常使用的打包插件shade,它的goal是绑定到package阶段的,这样,使用mvn package进行打包时都会执行shade的。

ShareMojo

goal为目标构建

虽然以phase为目标的构建最常见,但是有时候我们会发现,一些插件的goal并不适合绑定到任何阶段(phase)上,或者是,这些goal往往是单独执行,不需要同某个阶段(phase)绑定在一起,比如hibernate插件的导入\导出goal多数情况下是根据需要要手动执行的(当然,也可以绑定到某个阶段上,比如进行单元测试时,可考虑将其绑定到test阶段上)。再比如jetty(6.1.26)插件,它的goal都是将打包或未打包的工程部署到jetty里然后启动jetty容器的,多数情况下,人们都是独立运行这些goal的,比如:人们希望当键入mvn jetty:run后,工程就能完成编译后启动jetty,jetty插件也确实是这样做的,它的run goalmojo是这样声明的:

Jetty6RunMojo

其中@execute phase=test-compile"指明jetty:run这一goal会促使mavenbuildtest-compile阶段,再执行这个goal.同样,对于jetty:run-war这个goal则要求先buildpackage阶段再执行该goal

Jetty6RunWar

而另外一个例子是exec插件的exec:java

ExecJavaMojo

这个goal也声明了executephase,但却是validate,这样,如果代码没有编译,执行这个goal就会出错,所以多数情况下,人们总是使用下面的方式执行的:mvn clean compile exec:java

上一页
下一页