1、什么是生命周期?插件的作用?

前面我们说过,maven是一个项目构建、依赖管理的工具,生命周期就是maven在项目构建的过程中抽象出来的一系列子过程,例如编译、执行测试、打包等等过程。
需要注意的是,maven只是将生命周期进行了抽象化的定义,真正实现生命周期各个过程是插件。这样做的好处是,可以最大限度的将定制构建行为的能力提供给开发人员,开发人员甚至可以自己编写自己需要的插件,来满足自己的特性化构建需求。

2、maven的生命周期

2.1、maven的三套生命周期

对于maven的生命周期来说,共有三个相互独立的生命周期,分别是clean、default、site。

  • clean生命周期目的是清理项目
  • default生命周期目的是构建项目
  • site生命周期目的是建立项目站点。

每个生命周期分别包含一些阶段,这些阶段是有顺序的,并且后面的阶段依赖于前面的阶段。如clean生命周期包含pre-clean、clean和post-clean三个阶段,如果执行clean阶段,则会先执行pre-clean阶段。
较之于生命周期阶段有前后依赖关系,三套生命周期本身是相互独立的,用户可以仅调用clean生命周期的某个阶段,也可以不执行clean周期,而直接执行default生命周期的某几个阶段。

2.2、clean生命周期

clean生命周期包含三个阶段,主要负责清理项目,如下:

pre-clean

executes processes needed prior to the actual project cleaning

clean

remove all files generated by the previous build

post-clean

executes processes needed to finalize the project cleaning

2.3、default生命周期

default生命周期定义了真正构建时所需要执行的所有步骤,包含的阶段如下:

validate

validate the project is correct and all necessary information is available.

initialize

initialize build state, e.g. set properties or create directories.

generate-sources

generate any source code for inclusion in compilation.

process-sources

处理项目的主资源文件,一般来说,是对src/main/resources目录的内容进行变量替换等工作后,复制到项目输出的主classpath目录中

generate-resources

generate resources for inclusion in the package.

process-resources

copy and process the resources into the destination directory, ready for packaging.

compile

编译项目的主源码,一般来说是编译src/main/java目录下的JAVA文件至项目的主classpath目录中

process-classes

post-process the generated files from compilation, for example to do bytecode enhancement on Java classes.

generate-test-sources

generate any test source code for inclusion in compilation.

process-test-sources

处理项目测试资源文件

generate-test-resources

create resources for testing.

process-test-resources

copy and process the resources into the test destination directory.

test-compile

编译项目的测试代码

process-test-classes

post-process the generated files from test compilation, for example to do bytecode enhancement on Java classes. For Maven 2.0.5 and above.

test

使用合适的单元测试框架运行测试。这些测试不应该要求对代码进行打包或部署。

prepare-package

perform any operations necessary to prepare a package before the actual packaging. This often results in an unpacked, processed version of the package. (Maven 2.1 and above)

package

将编译后的代码打包成可分发的格式,例如JAR。

pre-integration-test

perform actions required before integration tests are executed. This may involve things such as setting up the required environment.

integration-test

process and deploy the package if necessary into an environment where integration tests can be run.

post-integration-test

perform actions required after integration tests have been executed. This may including cleaning up the environment.

verify

run any checks to verify the package is valid and meets quality criteria.

install

将包安装到本地存储库中,以便在本地其他项目中作为依赖项使用。

deploy

在集成或发布环境中完成,将最终包复制到远程存储库,以便与其他开发人员和项目共享。

2.4、site生命周期

siet生命周期的目的是建立和发布项目站点,maven能够基于POM所包含的信息,自动生成一个友好的站点,方便团队交流和发布项目信息,包含的阶段如下:

pre-site

在实际项目站点生成之前执行所需的过程

site

生成项目的站点文档

post-site

执行完成站点生成和准备站点部署所需的过程

site-deploy

将生成的站点文档部署到指定的web服务器

2.5、命令行和生命周期

从命令行执行maven任务的最主要方式就是调用maven的生命周期阶段。需要注意的是,各个生命周期是相互独立的,而一个生命周期的阶段是有前后依赖关系的。例子如下:

  • $mvn clean :该命令调用clean生命周期的clean阶段。实际执行的阶段为clean生命周期的pre-clean和clean阶段。
  • $mvn test:该命令调用default生命周期的test阶段。实际调用的是default生命周期的validate、initialize等,直到test的所有阶段。
  • $mvn clean install:该命令调换用clean生命周期的clean阶段和default生命周期的instal阶段。
  • $mvn clean deploy 该命令调用了clean生命周期的clean阶段、default生命周期的deploy阶段

3、插件

3.1、插件目标

maven的核心仅仅定义了抽象的生命周期,具体的任务是交由插件完成的,插件以独立的形式存在。
对于插件本身,为了能够复用代码,它往往能够完成多个任务。如maven-dependency-plugin有十多个目标,每个目标对应了一个功能,如 dependency:analyze、 dependency:tree和dependency:list。这是一种通用的写法,冒号前面是插件前缀,后面是该插件的目标。

3.2、插件绑定

maven的生命周期与插件相互绑定,用以完成实际的构建任务。具体而言,是生命周期的阶段与插件的目标相互绑定,已完成某个具体的构建任务。例如项目编译这一任务,它对应了default生命周期的compile阶段,而maven-compiler-plugin这一插件的compile目标能够完成该任务,因此将他们绑定。

maven的plugin保存在哪里_仓库

3.2.1、 内置绑定–maven默认构建行为

为了让用户能够不用任何配置就能构建maven项目,maven在核心为一些主要的生命周期默认绑定了很多插件的目标,当用户通过命令行调用生命周期阶段的时候,对应的插件目标就会执行相应的任务。
clean和site生命周期绑定的插件目标相对简单。

clean生命周期阶段

插件目标

pre-clean

clean

maven-clean-plugin:clean

post-clean

default生命周期默认插件目标绑定

deafult生命周期的阶段和插件目标的绑定关系由项目的打包理性决定(jar or war)

process-resources

resources:resources

复制主资源文件至主输出目录

compile

compiler:compile

编译主代码至主输出目录

process-test-resources

resources:testResources

复制测试资源文件至测试输出目录

test-compile

compiler:testCompile

编译测试代码至测试输出目录

test

surefire:test

执行测试用例

package

ejb:ejb or ejb3:ejb3 or jar:jar or par:par or rar:rar or war:war

打包

install

install:install

将项目输出构件安装到本地仓库

deploy

deploy:deploy

将项目输出构件安装到远程仓库

注意:上面只列出了拥有插件绑定关系的阶段,default生命周期还有很多其他阶段,默认它们没有绑定任何插件

3.2.2、自定义绑定

除了内置绑定以为,用户还能够自己选择奖某个插件目标绑定到生命周期的某个阶段以执行更多更特色的任务。
pom中自定义绑定插件目标

<!-- 自动复制maven依赖包到lib目录 -->  
<build>
    <plugins>
            <plugin>  
                <groupId>org.apache.maven.plugins</groupId>  
                <artifactId>maven-dependency-plugin</artifactId>  
                <version>2.1</version>  
                <executions>  <!--配置执行任务-->
                    <execution>  
                        <id>copy</id>  
                        <phase>install</phase><!--绑定生命周期-->  
                        <goals>  <!--绑定插件目标-->
                            <goal>copy-dependencies</goal>  
                        </goals>  
                        <configuration><!--配置插件参数-->  
                            <outputDirectory>lib</outputDirectory>  
                        </configuration>  
                    </execution>  
                </executions>  
            </plugin>  
   </plugins>
</build>

上面的配置,定义了一个id为copy的任务,利用插件maven-dependency-plugin的copy-dependencies目标绑定到default生命周期的install阶段,来实现项目依赖的jar包的自动复制。
注意: 当插件目标被绑定到不同的生命周期阶段时候,其执行顺序会有生命周期阶段的先后顺序决定的。如果多个目标被绑定到同一个阶段,他们的执行顺序是由插件声明的先后顺序决定目标的执行顺序。

3.3、插件配置

3.3.1、通过命令行配置

如 $mvn install -Dmaven.test.skip=true 的意义即跳过测试步骤。
参数-D的Java自带的,其功能是通过命令行设置一个java系统属性,maven简单地重用了该参数以实现插件参数的配置。

3.3.2、在pom中进行全局配置

如项目编译使用1.6版本的源文件,生成与JVM1.6兼容的字节码文件:

<plugin>  
           <groupId>org.apache.maven.plugins</groupId>  
           <artifactId>maven-compiler-plugin</artifactId>  
           <version>2.3.2</version>  
           <configuration> <!--参数配置-->  
               <source>1.6</source>  
               <target>1.6</target>  
           </configuration>  
        </plugin>

3.4、利用目标前缀,在命令行调用插件

我们可以通过mvn命令激活生命周期阶段(例如mvn install)来执行绑定在生命周期阶段的插件目标,同时我们也可以直接调用插件的目标。
调用方式:

mvn groupId:artifactId:version:goal

例如调用显示依赖树的插件目标:
mvn org.apache.maven.plugins:maven-dependency-plugin:2.1:tree
输入完之后,你肯定会觉得,这命令是不是太长了????!!!!!
于是,maven提供了目标前缀的概念。
maven将dependency作为 org.apache.maven.plugins:maven-dependency-plugin前缀,使用

mvn dependency:tree

来调用插件目标。

3.5、插件仓库

我们前面了解过依赖构件的仓库,同样的,插件构件同样也存在于maven仓库中,但是Maven会区别对待依赖的远程仓库和插件的远程仓库。
pom中配置一个插件构件的远程仓库:(也可在setting中配置)

<pluginRepositories>    
    <pluginRepository>    
        <id>central</id>    
        <name>Maven plugin</name>    
        <url>htpp://repo1.maven.org/maven2</url>    
        <layout>default</layout>    
        <snapshots>    
            <enabled>true</enabled>    
        </snapshots>    
        <releases>    
            <enabled>false</enabled>    
        </releases>    
    </pluginRepository>    
</pluginRepositories>

配置内容与依赖的远程仓库配置元素相同,此处不予赘述。