Maven生命周期和插件的那些事(2021版)

前言:在日常开发中我们经常使用IDE提供的MAVEN功能,如下图所示,通过右键->run maven build的方式或者通过命令行运行maven命令的方式来对项目进行构建。在我们通过简单操作就可以对项目进行clean(清理)、default(包括校验、编译、打包、测试等)、site(部署),在背后有好多知识点,本篇博客就对这些知识点进行整理归纳。

一、什么是Maven的生命周期:

在没有Maven之前,每个项目的开发人员一般都会干这么几件事情:清理、编译、测试和部署。不同的公司以及不同的项目之间,大家往往使用不同的方式做着类似的工作。刚刚说的那四件事也就是构建一个项目的生命周期。Maven从大量项目和构建工具(Maven之前也是有构建工具的)中学习和反思,对所有的构建过程进行抽象和统一,总结出现在Maven的生命周期。这个生命周期包含了项目的清理、初始化、编译、测试、打包、集成测试、验证、部署和站点生成等几乎所有项目构建步骤;

重点:Maven的生命周期是抽象的,就好比Java中的抽象方法,只声明生命周期和阶段,但本身不做任何实际的工作,实际工作都交由插件来完成;相当于Maven定义算法的整体结构,各个插件来实现实际的行为,保证了可扩展性的同时,又严格控制了生命周期结构,优点不言而喻。下面通过下面这个图,简单来说比如我们运行clean,Maven实际调用的是maven-clean-plugin插件的clean(目标)完成的项目结构清理功能,所有生命周期阶段都会有相应的插件完成具体功能。

每个Maven构建步骤都可以绑定一个或多个插件行为(goal),同时Maven也为大多数构建步骤编写并绑定了默认插件。需要注意的是默认插件只提供默认行为实现,当有特殊需要时,比如我们在打包Springboot项目成jar包时,那样就需要引入和配置spring-boot-maven-plugin来完成打包需求。

二、三套生命周期

通过上图,大部分人会以为Maven的生命周期是一体的,即从clean->...->deploy,其实不然。Maven有三套独立的生命周期,分别为clean(清理项目)、default(构建项目)、site(建立项目站点)。每个项目周期又分为不同的阶段,比如clean生命周期下的阶段依次为:pre-clean->clean->post-clean,用户通过命令行也好,IDE提供的帮助也罢,执行Maven任务的最主要方式就是调用这些生命周期的阶段。这些生命周期的阶段是有顺序的,并且后面阶段的执行依赖于前面阶段。还是拿clean生命周期举例子:当我们调用post-clean阶段时,由于这个阶段前面存在pre-clean和clean两个阶段,最终pre-clean、clean和post-clean会得以顺序执行。其实这个现象开发过程中常见,比如我们在通过package打包springboot项目时,编译、测试、打包都得以执行。由于每个生命周期,特别是default,包含了多个阶段,在此就不一一列举了,只需要把每个生命周期的起止边界记清楚就可以了。

需要注意的是同一个生命周期的阶段调用是顺序执行,但不同生命周期间的阶段是独立的,这也就是为什么我们会用mvn clean package 这个命令对项目打包的原因了,因为clean和package分属于不同生命周期阶段。

三、插件目标:Maven的核心仅仅是定义了抽象的生命周期以及具体任务分发个具体插件执行。所以咱们接下来说说插件,先不解释,直接看图,以常见的spring-boot-maven-plugin插件举例

对于一个插件本身而言,它往往能够完成多个任务,一般来说不太可能一个任务对应一个插件。每个可以完成的任务(或者叫做插件的功能)咱们把它称作一个插件目标(goal),像spring-boot-maven-plugin插件有六个目标(goal)。每个goal的名称有英文冒号分隔,黄色框内的叫做插件前缀,绿色框内的称为插件goal。通常spring-boot:repackage就代指spring-boot-maven-plugin插件的repackage功能。

四、插件绑定

指的是Maven的生命周期和插件绑定,具体指的是Maven生命周期的阶段与插件的目标进行绑定,以完成某个构建任务。比如default生命周期中的install阶段就是与maven-install-plugin的install(install:install)目标进行绑定来完成安装包到本地仓库的任务。

内置绑定:为了让用户几乎不做任何配置就能构建Maven项目,Maven核心中就默认为一些主要的生命周期阶段绑定了很多插件的目标。内置绑定大致如下,大家简单看下即可,如果英文好一些,根据名称就可以大致了解的;

default生命周期拥有众多阶段,下表只是列出具有插件目标绑定的生命周期阶段

以下是对一个springboot项目调用mvn install的输出日志,已删除非重要内容,通过以下日志可以看出插件的执行过程:

自定义绑定:除了内置定义外我们也可以在pom文件中通过自定义plugin配置完成个性化的任务。比如我们在default生命周期的package阶段,在打包jar包的同时,把代码也打包。那么我们就可以在pom文件的plugins中增加如下配置完成该任务:

<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-source-plugin</artifactId>
	<version>2.1.1</version>
	<executions>
		<execution>
			<id>attach-source</id>
			<phase>package</phase>
			<goals>
				<goal>jar-no-fork</goal>
			</goals>
		</execution>
	</executions>
</plugin>

简单解释下以上配置作用,即将maven-source-plugin插件的jar-no-fork目标绑定到phase元素指定的package阶段,即实现在根据编译好的代码打包的同时对源码也实现打包,日志输出如下图:

这个时候有的人可能要说了,你看下面这个配置也并没有指定生命周期的哪个阶段与插件目标进行绑定,一样可以使用这个插件的打包功能。

<plugin>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>

那是因为有些插件的目标在实现时已经定义了默认绑定阶段,我们可以通过以下命令查看,其中会发现默认绑定配置的

mvn help:describe -Dplugin=org.springframework.boot:spring-boot-maven-plugin:2.2.1.RELEASE -Ddetail

总结:本次重点介绍了Maven的生命周期和插件、生命周期的阶段和插件目标的概念、命令行和生命周期阶段的关系、生命周期和阶段的绑定等相关理论,相信懂了这些之后在使用IDE提供的Maven集成功能时会更近一步了解。

以上,完了!!

猜你喜欢

转载自blog.csdn.net/yu102655/article/details/112317985