maven plugin classloader加载class问题

1.       写一个基于maven的插件

今天在写基于maven plugin的一个小程序,它的功能是在maven执行package 阶段将已经打好包,从这个包中抽取分布式服务中依赖的类,之后会将这些服务器端依赖的类打成一个包。也就是执行了mvn package之后会在工程的target中生成两个jar包,一个是服务器端部署包,一个是客户端依赖包。客户端依赖包是服务器端包的一个子集。

    该插件就是负责抽取服务器端部署包中的类。插件的工程名称是distribute-build,插件开发完成之后,会在具体的项目中使用,我搞了一个实验项目koubei-dian,koubei-dian 这个分包项目中的pom中增加一个插件的配置节点,如下所示

 

<project >
    <modelVersion>4.0.0</modelVersion>
    <build>
       <plugins>
           <plugin>
              <groupId>com.koubei</groupId>
              <artifactId>distribute-build</artifactId>
              <version>1.0-SNAPSHOT</version>
              <configuration>
                  <springConfig>dian.application.xml</springConfig>
                  <port>9999</port>
              </configuration>
           </plugin>
       </plugins>
    </build>
</project>

 

2.   发现问题

然后在dos命令行中敲入下面这个命令:

 

\koubei-dian>mvn com.koubei:distribute-build:distill

但是在执行distill这个goal时候出现了错误

 

java.lang.NoClassDefFoundError: com/koubei/util/Pager

        at java.lang.Class.getDeclaredMethods0(Native Method)

        at java.lang.Class.privateGetDeclaredMethods(Class.java:2427)

        at java.lang.Class.privateGetPublicMethods(Class.java:2547)

        at java.lang.Class.getMethods(Class.java:1410)

        at com.koubei.plugin.distribute.ClassMetaInfo.getAllDepandClass(ClassMet

aInfo.java:51)

        at com.koubei.plugin.distribute.ServiceClassManager.execute(ServiceClass

Manager.java:109)

        at org.apache.maven.plugin.DefaultPluginManager.executeMojo(DefaultPlugi

nManager.java:483)

        at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoals(Defa

ultLifecycleExecutor.java:678)

        at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeStandalone

Goal(DefaultLifecycleExecutor.java:553)

        at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoal(Defau

ltLifecycleExecutor.java:523)

        at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalAndHan

dleFailures(DefaultLifecycleExecutor.java:371)

        at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeTaskSegmen

ts(DefaultLifecycleExecutor.java:332)

        at org.apache.maven.lifecycle.DefaultLifecycleExecutor.execute(DefaultLi

fecycleExecutor.java:181)

奇怪!我明明已经在koubeid-dianpom中的depandance中添加了com/koubei/util/Pager 这个类所在包的依赖呀,为啥当前的classloader还是不能加载这个类呢?直觉告诉我应该是mavenclassloader的加载机制的问题。于是还得依赖万能的google,终于我找到了maven reference网站上关于maven类加载机制的说明。http://maven.apache.org/guides/mini/guide-maven-classloading.html   

这个文档中说了四种类加载机制,分别是:

1.         System Classloader

2.         Core Classloader

3.         Plugin Classloaders

4.         Custom Classloaders

其中我最关心的是plugin classloaders,这个类加载器从类加载的层次关系来看是继承与System classloader Core Classloader的,凭我想当然的理解在插件goal执行的时候插件的classloader已经包含的project pom 中申明的依赖包。但是,plugin classloader说明中有这么一句话:

 

Please note that the plugin classloader does neither contain the dependencies of the current project nor its build output. Instead, plugins can query the project's compile, runtime and test class path from the MavenProject in combination with the mojo annotation requiresDependencyResolution from the Mojo API Specification. For instance, flagging a mojo with @requiresDependencyResolution runtime enables it to query the runtime class path of the current project from which it could create further classloaders.

 

翻译一下:

 

    请注意,plugin classloader既不包含当前工程的dependencies,也不包含当前工程的输出目录。但是,如果你现在插件运行的时候想引用当前工程的编译(compile)、运行时(runtime)、测试(test)的classpath,可以通过MavenProject 这个组合在成员对象来调用,这个mojo对象需要有“requiresDependencyResolution”这个annotation

3.   解决问题

通过以上说明,我知道解决当前maven plugin 不能正常加载类的问题可以通过两个方法解决:

方法1:在plugin配置的时候为plugin配置节点单独配置一个dependacne

 

<project >

    <modelVersion>4.0.0</modelVersion>

    <build>

.。。。。。。。。。

       <plugins>

           <plugin>

              <groupId>com.koubei</groupId>

              <artifactId>distribute-build</artifactId>

              <version>1.0-SNAPSHOT</version>

              <configuration>

                  <springConfig>dian.application.xml</springConfig>

                  <port>9999</port>

              </configuration>

<dependencies>

                  <dependency>

                     <groupId>com.koubei</groupId>

                     <artifactId>koubei-util</artifactId>

                     <version>1.0.0</version>

                  </dependency>

              </dependencies>         

</plugin>

           。。。。。。。。。

       </plugins>

    </build>

</project>

添加如上蓝色加粗的dependencies节点。

方法2:在plugin类中添加MavenProject 一个成员对象,然后再类级别注释上添加@requiresDependencyResolution runtime注释项

 

1.       /**  

2.        * @goal extract  

3.        * @phase package  

4.        * @requiresDependencyResolution test  

5.        */  

6.       public class ServiceClassManager extends AbstractMojo {   

7.              

8.           /**  

9.            * @parameter default-value="${project}"  

10.        * @required  

11.        * @readonly  

12.        */  

13.       private MavenProject project;   

14.          

15.       public void execute() throws MojoExecutionException {   

16.              

17.           System.out.println(project.getArtifact().getFile().getAbsolutePath());   

18.              

19.       }   

20.   }  

 

通过以上这种方式就可以达到,不需要在plugin配置节点额外添加配置依赖来达到能够取道pom compile阶段需要依赖的那些jar包了。

完。。。。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值