我熟悉Maven插件开发,我需要一个问题的帮助。

据我了解,将复杂的对象传递给Maven插件非常容易,但是传递类呢?
可以说我正在编写自己的仅包含2个类的插件。

Message.java

package abstractmessage;
public abstract class Message {
    public abstract String getMessage();
}


MessageMojo.java

/**
 * @goal message
 */
public class MessageMojo extends AbstractMojo {
    /**
     * @parameter expression="${message.messageClass}"
     */
    private String messageClass ;

    @Override
    public void execute() throws MojoExecutionException, MojoFailureException {
        Message message = null;

        try {
            Class<?> clazz = Class.forName(messageClass);
            message = (Message) clazz.newInstance();
        } catch (Exception e) {
            getLog().error(e);
        }

        getLog().info(message.getMessage());
    }
}


因此,插件需要扩展Message类的名称,并尝试对其进行动态初始化。

在实际的Maven-Project中扩展的Message类如下所示。

package message;
import abstractmessage.Message;

public class RealMessage extends Message {
    @Override
    public String getMessage() {
        return "Hello plugin. From MavenProject.";
    }
}


pom.xml使用该插件。

<build>
    <plugins>
        <plugin>
            <artifactId>message-plugin</artifactId>
            <groupId>message-plugin</groupId>
            <version>1.0</version>
            <executions>
                <execution>
                    <phase>test</phase>
                    <goals>
                        <goal>message</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <messageClass>message.RealMessage</messageClass>
            </configuration>
        </plugin>
    </plugins>
</build>

<dependencies>
    <dependency>
        <artifactId>message-plugin</artifactId>
        <groupId>message-plugin</groupId>
        <version>1.0</version>
    </dependency>
</dependencies>


但是当我执行maven:test时,我得到一个java.lang.ClassNotFoundException: message.RealMessage

为什么这样?

最佳答案

您的插件的类加载器无权访问项目的类。它只能访问自己的类及其依赖项。

您有两个选择。

方法一是制作一个新的类加载器,以从当前项目及其依赖项中加载类。 surefire plugin是执行此操作的插件的一个示例-它可以加载已编译的单元测试类,并在未处于fork模式时运行它们。

从依赖关系创建新的类加载器并不是一件容易的事,但是首先,您需要在Mojo上放置@requiresDependencyResolution test,并抓住项目的依赖关系(如果要包含的话,还有项目的build输出目录)搜索中的项目类),然后从这些JAR和目录中构造一个URLClassLoader。 Surefire的generateTestClasspath() method可能会作为起点。

另一种选择是在单独的项目中编译RealMessage类,构建单独的JAR,并将其作为对消息插件的依赖。

在这种情况下,您的构建部分如下所示:

<build>
    <plugins>
        <plugin>
            <artifactId>message-plugin</artifactId>
            <groupId>message-plugin</groupId>
            <version>1.0</version>
            <executions>
                <execution>
                    <phase>test</phase>
                    <goals>
                        <goal>message</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <messageClass>message.RealMessage</messageClass>
            </configuration>
            <dependencies>
                <groupId>message-plugin-additions</groupId>
                <artifactId>message-plugin-additions</artifactId>
                <version>1.0</version>
            </dependencies>
        </plugin>
    </plugins>
</build>


其中message-plugin-additions项目包含message.RealMessage类。如果您愿意使用一个单独的项目,这可能会比第一种选择简单得多。

09-10 02:11
查看更多