maven插件开发

一 maven 框架

    maven官方文档介绍Apache Maven 2.2.x是一个项目开发和集成的工具,它建立在项目模型对象(PMO)基础之上,所有构建、依赖管理、文档创建、站点发布, 分发都在pom.xml文件中控制. Maven是可以用插件来扩展。它的框架如下:(2.2.x)

maven框架

 

 

maven3.x框架结构如下
maven3.x

 

二 Maven属性

      使用插件来扩展maven功能,必须先了解maven可访问的属性,maven属性在前一小节已经有过简单介绍,这里再展开讨论下。

      在pom.xml中可以使用Maven属性,格式为${属性名},在Maven项目中可以使用隐式属性如project.*(应用pom文件中project属性),setting.*(访问setting.xml文件中属性),env.*(访问环境变量属性,如path和MAVEN_HOME),系统属性(通过java中System.getProperty()能拿到的属性)。下面分别介绍这些属性:

      1 项目属性

         当你使用该隐式变量引用属性的时候,你实际上正在使用简单的点标记来引用Model对象的一个bean属性。例如,当你引用0.6-SNAPSHOT的时候,你实际上是在调用暴露出来的Model对象实例的getVersion()方法。任何在Maven POM 中的东西都可以用属性来引用,比如pom.xml中有

 

<groupId>org.sonatype.group1</groupId>
<artifactId>sibling-project</artifactId>
<version>0.6-SNAPSHOT</version>

 project.groupId 和 project.version 分别为org.sonatype.group1和0.6-SNAPSHOT

 

在一个POM中有数百的属性可以引用,具体可以参考pom的完整结构http://maven.apache.org/ref/2.2.1/maven-model/apidocs/index.html,查看org.apache.maven.model这个类的javadoc文档,能够找到想要的项目属性。

 

   2 setting属性

    任何Maven本地Settings文件的属性都可以被引用,该文件通常位于~/.m2/settings.xml。这个文件包含了用户特定的配置,如本地仓库的位置,以及由某个特定用户配置的服务器,profile,和镜像,setting的具体属性可以参考http://maven.apache.org/ref/2.2.1/maven-settings/index.html中Maven Settings Model的javadoc

 

   3 环境变量属性

    env.PATH, env.HOME, env.JAVA_HOME, env.MAVEN_HOME

    虽然他们都是可用的,但如果你有选择,你更应该使用Java系统属性

 

    4 Java系统属性

    Maven暴露所有来自于java.lang.System的属性。任何你能从System.getProperty()获取的属性都能以Maven属性的形式引用

java.versionJava运行环境版本java.vendorJava运行环境供应商
java.vendor.urlJava供应商URLjava.homeJava安装目录
java.vm.specification.versionJava虚拟机规格说明版本java.vm.specification.vendor Java虚拟机规格说明供应商
java.vm.specification.nameJava虚拟机规格说明名称java.vm.versionJava虚拟机实现版本
java.vm.vendorJava虚拟机实现供应商java.vm.nameJava虚拟机实现名称
java.specification.versionJava运行环境规格说明版本java.specification.vendorJava运行环境规格说明供应商
java.specification.nameJava运行环境规格说明名称java.class.versionJava类格式版本号
java.class.pathJava类路径java.ext.dirs扩展目录的路径
os.name操作系统名称os.arch操作系统架构
os.version操作系统版本file.separator文件分隔符(UNIX上是"/",Windows上是"\")
path.separator路径分隔符(UNIX上是":",Windows上是";")line.separator 行分隔符(在UNIX和Windows上都是"\n")
user.name用户帐户名称user.home用户home目录
user.dir用户当前工作目录  

 

    5 用户定义属性

这类属性可以定义在POM或者Profile中,而这些在POM或者MavenProfile中设置的属性可以像任何其它Maven属性一样被引用。

<properties>
<arbitrary.property.a>This is some text</arbitrary.property.a>
<hibernate.version>3.3.0.ga</hibernate.version>
</properties>

 

<profiles>
<profile>
<id>some-profile</id>
<properties>
<arbitrary.property>This is some text</arbitrary.property>
</properties>
</profile>
</profiles>

 

 

在资源中引用属性,可以使用外部资源文件,如开启maven的filter过滤资源,默认maven的filter文件路径为src/main/filters/目录,也可以在pom中设置到其他路径,比如想用default.properties的属性替换掉资源文件里的占位符,目录路径为:



 

service.xml内容为:

<?xml version="1.0" encoding="UTF-8"?>
<service>
<!-- This URL was set by project version 0.6-SNAPSHOT -->
<url>${jdbc.url}</url>
<user>${jdbc.username}</user>
<password>${jdbc.password}</password>
</service>
</xml>

 

 default.properties内容为:

jdbc.url=jdbc:hsqldb:mem:mydb
jdbc.username=admin
jdbc.password=

 pom.xml filter设置为:

<project>
....
<properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
....
<build>
		<finalName>simple-webapp</finalName>
		<filters>
			<filter>src/main/filters/default.properties</filter>
		</filters>
		<resources>
			<resource>
				<directory>src/main/resources</directory>
				<filtering>true</filtering>
			</resource>
		</resources>		
	</build>
....
</project>

 

 开启资源过滤后(资源过滤默认是关闭的),运行mvn resources:resources后,target目录下target\classes\META-INF\service.xml占位符会被properties文件具体值替换掉。

 

 

三 maven 插件

 

1 反转控制(IOC)

Maven的心脏是一个名为Plexus的反转控制(IoC)框架,它是一个用来管理及关联组件的系统。用Java实现的IoC容器中,最重要的一个功能是称作依赖注入的机制。IoC的基本想法是将对象的创建和管理从代码中剥离,并将控制放到IoC框架手中。在一个面向接口编程的应用程序中使用依赖注入,你创建的组件可以不与任何特定的接口实现绑定。你的程序也针对接口编程并通过配置Plexus来将正确的实现连接到正确的组件。虽然你的代码都是与接口打交道,但你仍然可以通过一个定义组件的XML文件来获得类和组件相互依赖的信息。换句话说,你可以编写独立的组件,然后你可以通过一个XML文件来定义组件应当如何被装配在一起。在Plexus的情形中,定义系统组件的XML文档位于META-INF/plexus/components.xml。在一个Java IoC容器中,有很多中方法将依赖值注入到一个组件对象中:构造器,set方法,或者字段注入。虽然Plexus提供全部这三种依赖注入技术,Maven只使用其中的两种:字段注入和set方法注入。

      目前Spring是最流行的IoC容器。它影响了Java的“生态系统”,迫使如SunMicrosystems之类的公司让出更多的对于开源社区的控制,并通过提供一个更易插入的,面向组件的“总线”来帮助开发一些标准,当Maven被创建的时候,Spring并不是一个成熟的选项。最初的Maven提交者团队更熟悉Plexus因为正是他们发明了Plexus,因此他们决定使用Plexus做为Ioc容器。虽然它没有Spring Framework流行,但并不是说它的功能没那么强大。

     

2 插件

      一个Maven插件是包含了一个插件描述符和一个或者多个Mojo的Maven构件。一个Mojo可以被认为是Maven中的一个目标,每一个目标对应了一个Mojo。compiler:compile目标对应了Maven Compiler插件的CompilerMojo类,jar:jar目标对应了Maven Jar插件的JarMojo类。当你编写自己的插件的时候,你在一个单独的插件构件中将一组相互关联的Mojo(或者目标)归类。(Maven使用术语Mojo因为这是一个对于Pojo(Plan-oldJava Object)的玩笑),Mojo不仅仅是Maven中的一个目标,它是一个由Plexus管理的组件,可以引用其它Plexus组件。

 

1)插件描述符

Maven插件包含了一个告诉Maven各种Mojo和插件配置的路线图。这就是插件描述符,它位于JAR文件中的META-INF/maven/plugin.xml。当Maven载入一个插件的时候,它读取该XML文件,初始化并配置插件对象,使Mojo被包含在插件中,供Maven使用。当你编写自定义Maven插件的时候,你几乎不需要编写插件描述符。在构 建生命周期中,绑定到maven-plugin打包类型的生命周期目标显示,plugin:descriptor目标被绑定到了generate-resources生命周期阶段。该目标根据插件源码中的注解生成一个插件描述符,plugin.xml定义三部分内容:坐标信息、mojo声明、依赖声明。

description该元素包含了插件的简短描述。
groupId, artifactId, version就像Maven中的任何其它构件一样,插件也需要唯一的坐标
goalPrefix该元素(目标前缀)用来设置某个特定插件用来引用目标的前缀
isolatedRealm该遗留属性不再被Maven使用。它的存在是为了给旧的插件提供向后兼容性早期版本的Maven。使用它提供一种在单独ClassLoader中载入插件依赖的机制
inheritedByDefault如果inheritedByDefault(缺省继承)被设置成true,所有在父项目配置的该插件的mojo会在子项目中生效inheritedByDefault没有被设置成true,那么定义在父项目中的目标执行不会被子项目继承
mojo配置 
goal这是目标的名称。如果你在运行compiler:compile目标,compiler就是插件的goalPrefix,compile就是目标的名称。
description目标的简要描述,当用户使用Help插件生成插件文档的时候,该描述会被显示
requiresDirectInvocation如果你将其设置成true,那么该目标就只能由用户在命令行显示的执行。如果有人想要将该目标绑定到一个生命周期阶段,Maven会打印错误信息。该元素默认值是false。
requiresProject指定该目标不能在项目外部运行。目标需要一个带有POM的项目。requiresProject默认的值为true。
requiresReports如果你正创建一个插件,它依赖于报告,那么你就需要将requiresReports设置成true。例如,如果你创建一个插件用来聚合许多报告的信息,那么就需要将requiresReports设置成true。该元素默认的值为false。
aggregator当Mojo描述符的aggregator设置成true的时候,那么该目标只会在Maven执行的时候运行一次,提供该配置是为了让开发人员能够对一系列构建进行总结;例如,创建一个插件来概述构建中所有项目的一类报告。一个aggregator设置成true的目标应该只在Maven构建的顶层项目中运行。aggregator默认值是false。
requiresOnline指定当Maven在离线模式(-o命令行选项)的时候该目标不能运行,该元素默认值是false
inheritedByDefault如果inheritedByDefault被设置成true,在父项目中配置的mojo就会同样在子项目中被继承
phase如果用户没有为该目标绑定一个阶段,那么该元素定义一个mojo默认的阶段,若你没有指定phase元素,Maven就会要求用户在POM中显式的指定一个阶段
implementation该元素告诉Maven需要为该Mojo初始化什么类,这是一个Plexus组件属性(在Plexus ComponentDescriptor 中定义)
languageMaven Mojo默认的语言是java,该配置控制Plexus ComponentFactory初始化该Mojo组件
instantiationStrategy该属性是一个Plexus组件配置属性,它告诉Plexus如何创建和管理组件实例,Maven中,所有mojo的instantiationStrategy都被配置成per-lookup,每次Maven从Plexus获取该mojo的时候,一个新的实例被创建
executionStrategyexecutionStrategy告诉Maven什么时候,怎样运行一个Mojo,once-per-session和always,是早期版本遗留的
parameters该元素描述Mojo的所有参数。name,type,required,editable(是否允许在pom.xml中设置),description
configuration(为所有Mojo参数提供默认值)
requirements一个mojo是一个由Plexus管理的组件,它就有机会引用Plexus管理的其它组件。该元素能让你定义对于其它Plexus组件的依赖
  
  

 

2)编写插件

a)创建插件项目:

mvn archetype:create -DgroupId=org.sonatype.plugins -DartifactId=first-maven-plugin -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-mojo

 

运行mvn install 后,可以打开jar包(或者class目录中META-INF\maven)下pugin.xml插件描述文件:

  <?xml version="1.0" encoding="UTF-8" ?> 
- <plugin>
  <description /> 
  <groupId>org.sonatype.plugins</groupId> 
  <artifactId>first-maven-plugin</artifactId> 
  <version>1.0-SNAPSHOT</version> 
  <goalPrefix>first</goalPrefix> 
  <isolatedRealm>false</isolatedRealm> 
  <inheritedByDefault>true</inheritedByDefault> 
- <mojos>
- <mojo>
  <goal>touch</goal> 
  <description>Goal which touches a timestamp file.</description> 
  <requiresDirectInvocation>false</requiresDirectInvocation> 
  <requiresProject>true</requiresProject> 
  <requiresReports>false</requiresReports> 
  <aggregator>false</aggregator> 
  <requiresOnline>false</requiresOnline> 
  <inheritedByDefault>true</inheritedByDefault> 
  <phase>process-sources</phase> 
  <implementation>org.sonatype.plugins.MyMojo</implementation> 
  <language>java</language> 
  <instantiationStrategy>per-lookup</instantiationStrategy> 
  <executionStrategy>once-per-session</executionStrategy> 
- <parameters>
- <parameter>
  <name>outputDirectory</name> 
  <type>java.io.File</type> 
  <required>true</required> 
  <editable>true</editable> 
  <description>Location of the file.</description> 
  </parameter>
  </parameters>
- <configuration>
  <outputDirectory implementation="java.io.File">${project.build.directory}</outputDirectory> 
  </configuration>
  </mojo>
  </mojos>
- <dependencies>
- <dependency>
  <groupId>org.apache.maven</groupId> 
  <artifactId>maven-plugin-api</artifactId> 
  <type>jar</type> 
  <version>2.0</version> 
  </dependency>
  </dependencies>
  </plugin>

 

 

描述文件中显示有可运行的目标touch,且输入参数值为maven的project.build.directory 参数。

运行插件的touch目标 mvn org.sonatype.plugins:first-maven-plugin:touch 结果可以验证touch创建文件是否成功。

 

3)插件前缀

运行插件时需要带上插件的goupId,artifactId,version,目标,参数,尤其groupId和aritifaceId比较长,mavne提供了缩写方式,即可以自定义插件前缀。

如果未使用其他仓库,可以在本地Maven仓库径org/apache/maven/plugins/maven-metadata-central.xml文件中看到插件组org.apache.maven.plugins的Maven元数据

 

<?xml version="1.0" encoding="UTF-8"?>
<metadata>
<plugins>
<plugin>
<name>Maven Clean Plugin</name>
<prefix>clean</prefix>
<artifactId>maven-clean-plugin</artifactId>
</plugin>
<plugin>
<name>Maven Compiler Plugin</name>
<prefix>compiler</prefix>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
<plugin>
<name>Maven Surefire Plugin</name>
<prefix>surefire</prefix>
<artifactId>maven-surefire-plugin</artifactId>
</plugin>
...
</plugins>
</metadata>

 

 如果使用了其他仓库,比如setting.xml中配置了

<pluginGroups>

 <pluginGroup>com.xxx.org.apache.maven.plugins</pluginGroup>

<pluginGroup>com.my.maven.plugins</pluginGroup>

</ pluginGroups >

那么可以在本地仓库com\my\maven\plugins\maven-metadata-central.xml中查看插件组的元数据.

 

如果想要通过first:touch命令就能运行first-maven-plugin的touch目标,如所示,添加org.sonatype.plugins groupId至你的~/.m2/settings.xml文件中。这会让Maven优先扫描org.sonatype.plugins插件组

 

<settings>
...
<pluginGroups>
<pluginGroup>org.sonatype.plugins</pluginGroupd>
</pluginGroups>
</settings>
 这样子行得通是因为我们遵循了Maven插件的命名约定。如果你的插件有一个artifactId,并且它遵循模式maven-first-plugin,或者first-maven-plugin。Maven就会自动为你的插件赋予前缀first。换句话说,当Maven Plugin插件为你的插件生成插件描述符的时候,你不需要显式的为你的项目设定goalPrefix,###artifactId########,##plugin:descriptor目标会从你插件的artifactId中抽取前缀。${prefix}-maven-plugin, 或 maven-${prefix}-plugin,如果要显示配置插件,在插件pom.xml中配置
<build>
<plugins>
<plugin>
<artifactId>maven-plugin-plugin</artifactId>
<version>2.3</version>
<configuration>
<goalPrefix>blah</goalPrefix>
</configuration>
</plugin>
</plugins>
</build>
 

如果在~/.m2/settings.xml中的pluginGroups下添加了org.sonatype.plugins元素,你就应该能够在任何目录通过mvn blah:touch命令运行MyMojo

 

4)插件类注解

注解列表,可以用到Mojo类上

@goal <goalName>这是唯一必需的注解,它给予目标一个在插件中唯一的名称@requiresDependencyResolution <requireScope>标记该mojo在可以运行之前,需要特定范围或者一个暗指的范围)的依赖。支持的范围有compile,runtime,和test。如果该注解有一个值为test,那么就是告诉Maven,除非测试范围的所有依赖都被正确解析了,否则该mojo不能运行。
@requiresProject (true|false)标记该mojo必须在一个项目中运行,默认为true。这一点插件类型和骨架类型(archetype)相反,后者默认为false。@requiresReports (true|false)如果你正创建一个依赖于报告的项目,你就需要将requiresReports设置成true。该注解默认的值是false。
@aggregator (true|false)一个aggregator设置成true的Mojo在Maven运行的时候只会被执行一次,例如,创建一个插件用来汇总一次构建包含的所有项目的报告。aggregator设置成true的目标只针对Maven构建的顶层项目运行。该注解默认的值是false@requiresOnline (true|false)当该注解的值是true的时候,Maven在脱机模式运行的时候该目标运行就败。Maven会抛出一个错误。默认值:false。
@requiresDirectInvocation当设置成true的时候,只有当用户显式的从命令行触发的时候,该插件才能得以执行。如果有人试图将其绑定到一个生命周期阶段,Maven就会抛出一个错默认值是false@phase <phaseName>该注解指定目标默认的生命周期阶段。如果你将该目标的执行配置到了pom.xml而且没有指定一个阶段。Maven就会使用该注解的值将其绑定到一个默认的阶段
@execute [goal=goalName|phase=phaseName [lifecycle=lifecycleId]]

该注解有很多种使用方式。

@execute goal="<goal>" 会在执行当前目标之前运行声明的目标。目标名称使用prefix:goal标记指定。

@execute phase="<phase>"在执行当前生命周期之前,fork出另一个构建生命周期(直到指定的阶段)。如果没有指定生命周期,Maven会使用当前构建的生命周期

@execute lifecycle="<lifecycle>" phase="<phase>"会执行给定的生命周期。自定义的生命周期可以在META-INF/maven/lifecycle.xml中定义。

@execute phase="package" lifecycle="zip"@execute phase="compile"@execute goal="zip:zip"  

到Maven并没有使用Java 5的标准注解。而是使用了Commons Attributes6。在注解成为Java语言的一部分之前,CommonsAttributes为Java程序员提供了一种使用注解的方式。因为Maven必须支持Java比较老的版本,所以它不能使用任何Java 5的新特性。

 

4)mojo执行失败

当mojo的execute方法失败时,Mojo中的execute()方法抛出两个异会抛出两钟异常:

ojoExecutionException:一个MojoExecutionException应该是一个致命的异常,发生了一些不可恢复的错误。如果有什么事情导致构建完全终止,你就需要抛出一个MojoExecutionException;比如说你正试图往磁盘写数据,但没有可用空间。你希望停止构建并让用户看到“BUILD ERROR”信息。

 

MojoFailureException:相对没有那么严重。一个单元测试可以失败,或者MD5校验和可以失败;两者都是潜在的问题,但是你不会想要抛出一个异常去终止整个构建,当Maven遇到项目失败的时候,他会提供不同的“弹性”设置:

mvn -ff

最快失败模式:Maven会在遇到第一个失败的时候失败(停止)。

mvn -fae

最后失败模式:Maven会在构建最后失败(停止)。如果Maven refactor中一个

失败了,Maven会继续构建其它项目,并在构建最后报告失败。

mvn -fn

从不失败模式:Maven从来不会为一个失败停止,也不会报告失败。

 

5)Mojo参数
在mojo中可以使用注解来绑定参数,如

/**
* Any Object to print out.
* @parameter
* expression="${echo.message}"
* default-value="Hello Maven World"
*/
private Object message;

 参数message 绑定表达式为echo.message,如果mvn命令中传入 -Decho.message=aaa,那么aaa值将会赋给message参数。默认参数值取的是"Hello Maven World",默认参数值也可以取maven自带参数表达式。将值传给参数的方法,除了命令行之外,还可以在pom.xml或setting.xml中自定义,如:

<properties>
<echo.message>Hello Everybody</echo.message>
</properties>

 

还可以在pom的plugin中加入,如:

 

<build>
<plugins>
<plugin>
<groupId>org.sonatype.mavenbook.plugins</groupId>
<artifactId>first-maven-plugin</artifactId>
<version>1.0-SNAPSHOT</version>
<configuration>
<message>Hello Everybody!</message>
</configuration>
</plugin>
</plugins>
</build>

 如果我们想要在一个生命周期的不同阶段中运行EchoMojo两次,并且希望每次运行都能自定义message参数,我们可以在如下在POM中的execution级别配置这个参数值:

<build>
<plugins>
<plugin>
<groupId>org.sonatype.plugins</groupId>
<artifactId>first-maven-plugin</artifactId>
<version>1.0-SNAPSHOT</version>
<executions>
<execution>
<id>first-execution</id>
<phase>generate-resources</phase>
<goals>
<goal>echo</goal>
</goals>
<configuration>
<message>The Eagle has Landed!</message>
</configuration>
</execution>
<execution>
<id>second-execution</id>
<phase>validate</phase>
<goals>
<goal>echo</goal>
</goals>
<configuration>
<message>0.6-SNAPSHOT</message>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

 要配置一个多值的Mojo参数,你应该为这类参数使用一组元素。如果这个多值参数的名称是includes,你就可以使用一个includes元素,它包含一组include子元素。如果这个多值参数的名称是excludes,你就应该使用带有exclude子元素的excludes元素。要配置ZipMojo使其忽略所有以.txt及波浪号结尾的文件,你可以使用如下的插件配置。如:

<build>
<plugins>
<plugin>
<groupId>org.sonatype.plugins</groupId>
<artifactId>zip-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>**/*.txt</exclude>
<exclude>**/*~</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>

 其中zip插件的源码为:

/**
* Zips up the output directory.
* @goal zip
* @phase package
*/
public class ZipMojo extends AbstractMojo
{
/**
* The Zip archiver.
* @parameter expression="${component.org.codehaus.plexus.archiver.Archiver#zip}"
*/
private ZipArchiver zipArchiver;
/**
* Directory containing the build files.
* @parameter expression="/usr/local/hudson/hudson-home/jobs/maven-guide-zh-to-production/*/
private File buildDirectory;
/**
* Base directory of the project.
* @parameter expression="/usr/local/hudson/hudson-home/jobs/maven-guide-zh-to-production/*/
private File baseDirectory;
/**
* A set of file patterns to include in the zip.
* @parameter alias="includes"
*/
private String[] mIncludes;
/**
* A set of file patterns to exclude from the zip.
* @parameter alias="excludes"
*/
private String[] mExcludes;
public void setExcludes( String[] excludes ) { mExcludes = excludes; }
public void setIncludes( String[] includes ) { mIncludes = includes; }
public void execute()
throws MojoExecutionException
{
try {
zipArchiver.addDirectory( buildDirectory, includes, excludes );
zipArchiver.setDestFile( new File( baseDirectory, "output.zip" ) );
zipArchiver.createArchive();
} catch( Exception e ) {
throw new MojoExecutionException( "Could not zip", e );
}
}
}

 

6)依赖于一个Plexus组件

一个Mojo是一个由名为Plexus的Ioc容器管理的组件。Mojo可以通过使用@parameter#@component注解声明Mojo参数,然后依赖于其它Plexu管理的组件,ZipMojo使用@parameter注解依赖于一个Plexus组件,该依赖也可以使用@component注解来声明。如

/**
* The Zip archiver.
* @component role="org.codehaus.plexus.archiver.Archiver" roleHint="zip"
*/
private ZipArchiver zipArchiver;

 

当Maven初始化该Mojo的时候,它会尝试通过指定的role和role hint来获取Plexus组件。在该例中,这个Mojo关联到一个ZipArchiver组件,后者能帮助ZipMojo创建ZIP文件。

 

maven的plugin插件有个descriptor目标绑定到了generate-resources阶段,该目标根据Mojo的注解生成插件描述符。有下列注解可以用在参数上,虽然也可以在公有setter方法上使用这些注解,不过一般是使用在私有变量上:

@parameter [alias="someAlias"] [expression="${someExpression}"] [defaultvalue="value"]

@required

@readonly:如果使用该注解,用户就不能从POM直接配置这个参数

@component:告诉Maven使用Plexus组件填充该字段。一个正确的@component注解值如下:  @component role="org.codehaus.plexus.archiver.Archiver" roleHint="zip"

也可以使用@parameter expression="${component.org.codehaus.plexus.archiver.Archiver#zip}"

@deprecated:该参数以过期,不再推荐使用。

 

 7)创建自定义的生命周期

自定义生命周期必须在插件项目的META-INF/maven/lifecycle.xml文件中定义。你可以引入这个定义在src/main/resources下的META-INF/maven/lifecycle.xml文件

结合例子看下:项目目录结构如下

 

 

package org.mtp.plugins;

import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;

/**
 * 使用execute注解使用touch生命周期的goal
 * @goal after-touch
 * @execute lifecycle="touchcycle" phase="package"
 */
public class MyAfterLifeCycleMojo  extends AbstractMojo{

	@Override
	public void execute() throws MojoExecutionException, MojoFailureException {
		getLog().info("begin MyAfterLifeCycleMojo.");
		
		getLog().info("end MyAfterLifeCycleMojo.");
		
	}

}

package org.mtp.plugins;

import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
/**
 * 在 after-touch 目标之后执行此mojo
 * @goal after-cycle
 * @execute goal="after-touch"
 */
public class MyAfterMojo extends AbstractMojo{

	@Override
	public void execute() throws MojoExecutionException, MojoFailureException {
		getLog().info("begin MyAfterMojo.");
		
		getLog().info("end MyAfterMojo.");
		
	}

}

package org.mtp.plugins;

import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
/**
 * 在生命周期阶段compiles之后执行
 * @goal after-phase-resouces
 * @execute phase="compile"
 */
public class MyAfterPhaseMojo extends AbstractMojo{

	@Override
	public void execute() throws MojoExecutionException, MojoFailureException {
		getLog().info("begin MyAfterPhaseMojo.");
		
		getLog().info("end MyAfterPhaseMojo.");
		
	}

}
//MyMojo在上文中已经列出
 lifecycle.xml内容为:

 

 

<lifecycles>
	<lifecycle>
		<id>touchcycle</id>
		<phases>
			<phase>
				<id>package</id>
				<executions>
					<execution>
						<goals>
							<goal>touch</goal>
						</goals>
					</execution>
				</executions>
			</phase>
		</phases>
	</lifecycle>
</lifecycles>
 

 

 mvn install之后,可以分别运行几个goal看看效果

mvn blabla:after-cycle 会触发after-touch goal,after-touch会触发touchcycle的package,它会触发touch目标,所以执行的Mojo依次是MyMojo,MyAfterLifeCycleMojo,MyAfterMojo

mvn blabla:after-phase-resouces 会先触发compile阶段之前所有绑定的插件,所以触发结果为:

  

[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: 'blabla'.
[INFO] ------------------------------------------------------------------------
[INFO] Building first-maven-plugin Maven Mojo
[INFO]    task-segment: [blabla:after-phase-resouces]
[INFO] ------------------------------------------------------------------------
[INFO] Preparing blabla:after-phase-resouces
[INFO] [plugin:descriptor {execution: default-descriptor}]
[WARNING] Goal prefix is: blabla; Maven currently expects it to be first
[INFO] Using 2 extractors.
[INFO] Applying extractor for language: java
[INFO] Extractor for language: java found 4 mojo descriptors.
[INFO] Applying extractor for language: bsh
[INFO] Extractor for language: bsh found 0 mojo descriptors.
[INFO] [resources:resources {execution: default-resources}]
[WARNING] Using platform encoding (GBK actually) to copy filtered resources, i.e
. build is platform dependent!
[INFO] Copying 1 resource
[INFO] [compiler:compile {execution: default-compile}]
[INFO] Nothing to compile - all classes are up to date
[INFO] [blabla:after-phase-resouces {execution: default-cli}]
[INFO] begin MyAfterPhaseMojo.
[INFO] end MyAfterPhaseMojo.
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值