Maven plugin开发之classloader问题

本文第1,2节是maven插件开发的一些基础笔记。第3节是本文的重点,记录了笔者在开发maven插件时遇到的classloader问题。

1.如何做一个maven的plugin?

让你的类extends AbstractMojo,然后覆盖execute方法就可以了。
我的理解:maven的plugin可以做到只是一层壳,可以在execute里面再去调用核心的做事的类,由此可以充分发挥想象,做到任何java能做到的功能,比如调用代码生成器在generate-sources阶段生成代码。
要使用mojo的api,以下一些dependency是要加入的(有些不是必须,可以酌情删除)。

<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-descriptor</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-project</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-model</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-artifact</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>


2.${project.build.directory}表示什么意思
表示工程的target目录,
maven自带了哪些properties,可以参考http://docs.codehaus.org/display/MAVENUSER/MavenPropertiesGuide

3.classloader问题

3.1 maven在加载类方面使用了 [url=http://classworlds.codehaus.org/]ClassWorlds[/url]类库,所以是有一点复杂的。
一个典型的需求:如何在自己写的mojo里调用到某个特定jar包下的类呢。直接用Class.forName是会报类找不到的错的。
这点在官方文档上提到了一些。
http://maven.apache.org/guides/mini/guide-maven-classloading.html
其中第3节. Plugin Classloaders。这一节提到可以用 ${plugin.artifacts}这个表达式来得到运行时的依赖。

官方Cookbook给出了示例代码
http://docs.codehaus.org/display/MAVENUSER/Mojo+Developer+Cookbook


/** @parameter default-value="${plugin.artifacts}" */
private java.util.List pluginArtifacts;


我试验了以后发现是有问题的。首先用这个表达式Maven2和Maven3就不兼容,2种版本运行下来得到的dependency不一样。
其次即使得到了,dependency list也是不全的,这点可以在这个网页上得到佐证,http://maven.40175.n5.nabble.com/For-Plugin-Developers-Usage-of-plugin-artifacts-expression-td209073.html
maven在解析dependency的时候做了一点filter,所以这样就蛋疼了,得到的jar包不全,而我要的那个类所在的jar包就没有在这个解完的dependency list里。

3.2 classloader问题的一个解决方案:
http://stackoverflow.com/questions/871708/maven-plugin-cant-load-class/4921612#4921612

关键代码如下

List runtimeClasspathElements = project.getRuntimeClasspathElements();
URL[] runtimeUrls = new URL[runtimeClasspathElements.size()];
for (int i = 0; i < runtimeClasspathElements.size(); i++) {
String element = (String) runtimeClasspathElements.get(i);
runtimeUrls[i] = new File(element).toURI().toURL();
}
URLClassLoader newLoader = new URLClassLoader(runtimeUrls,
Thread.currentThread().getContextClassLoader());

这个方案我试过了,的确是可以的,但是Maven2和Maven3不兼容,还是这个问题,2种版本运行下来得到的dependency不一样。
而且有一个强制要求:你要的那个类所在的jar包必须加到你这个工程的dependency里去,采用compile phase,不然getRuntimeClasspathElements是得不到的。
问题是plugin需要什么jar那是plugin的事,为何要强制我工程加这个jar包呢,有时候我们不想让这个jar包进dependency,那怎么办呢?

3.3 classloader问题的另一个解决方案:
没辙了,只能把需要的jar包url当作参数传进mojo里来了,plugin怎么传参的可以在pom里<configuration>里面配置,具体就不展开了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值