Maven插件无法加载类

时间:2009-05-16 04:40:06

标签: maven-2 maven-plugin

我正在尝试制作一个需要使用反射的maven插件。我想要一个项目来运行插件,并在项目中为它提供类的全名,插件将通过反射加载它以从中获取信息。

但是类加载器有些奇怪,因为当我使用

时它找不到类
Class.forName("package.MyClass");

here,我无法弄清楚我的插件的类加载器是否可以访问该项目的类。

5 个答案:

答案 0 :(得分:16)

我确信有更好的方法,但这就是我如何让它发挥作用:

将以下内容添加到mojo顶部的javadoc:     @requiresDependencyResolution运行时

添加MavenProject参数:

/**
 * @parameter expression="${project}"
 * @required
 * @readonly
 */
private MavenProject project;

然后,您可以在运行时获取依赖项,并创建自己的类加载器:

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());

然后你可以使用这个新的类加载器加载你的类:

Class bundle = newLoader.loadClass("package.MyClass");

答案 1 :(得分:11)

您应该考虑使用它将运行时类路径元素添加到当前类领域。 (您可以使用PluginDescriptor来检索类领域。

List<String> runtimeClasspathElements = project.getRuntimeClasspathElements();
ClassRealm realm = descriptor.getClassRealm();

for (String element : runtimeClasspathElements)
{
    File elementFile = new File(element);
    realm.addURL(elementFile.toURI().toURL());
}

这对我来说非常合适!

正如Dave所说,这是获取PluginDescriptor的方法:

/**
 * The plugin descriptor
 * 
 * @parameter default-value="${descriptor}"
 */
private PluginDescriptor descriptor;

答案 2 :(得分:4)

今天我遇到了这个问题。以上建议对我不起作用,以为我会将我的解决方案提交到列表中。我使用了HibernateExporter mojo源,可以在http://grepcode.com/file/repo1.maven.org/maven2/org.codehaus.mojo/hibernate3-maven-plugin/2.2/org/codehaus/mojo/hibernate3/HibernateExporterMojo.java?av=f

查看
/**
 * @parameter expression="${project}"
 * @required
 * @readonly
 */
private MavenProject project;

private ClassLoader getClassLoader() throws MojoExecutionException
{
  try
  {
    List<String> classpathElements = project.getCompileClasspathElements();
    classpathElements.add(project.getBuild().getOutputDirectory() );
    classpathElements.add(project.getBuild().getTestOutputDirectory() );
    URL urls[] = new URL[classpathElements.size()];

    for ( int i = 0; i < classpathElements.size(); ++i )
    {
      urls[i] = new File( (String) classpathElements.get( i ) ).toURI().toURL();
    }
    return new URLClassLoader(urls, getClass().getClassLoader() );
  }
  catch (Exception e)//gotta catch em all
  {
    throw new MojoExecutionException("Couldn't create a classloader.", e);
  }
}

public void execute() throws MojoExecutionException
{
  ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
  Thread.currentThread().setContextClassLoader(getClassLoader());

   //... your code here ...
}

还要确保使用正确的MavenProject类。将此添加到您的pom

<dependency>
  <groupId>org.apache.maven</groupId>
  <artifactId>maven-core</artifactId>
  <version>3.0.3</version>
</dependency>

<dependency>
  <groupId>org.apache.maven</groupId>
  <artifactId>maven-plugin-api</artifactId>
  <version>3.0.3</version>
</dependency>

答案 3 :(得分:1)

这对我和maven3有用,可以将依赖项放入插件类路径中。

诀窍是使用@Component注入PluginDescriptor。否则将无法正确设置。

@Component
private MavenProject project;
@Component
private PluginDescriptor descriptor;

private void addDependenciesToClasspath(String artifactId) {
    for (Artifact artifact : project.getDependencyArtifacts()) {
        if (artifact.getArtifactId().equals(artifactId)) {
            try {
                final URL url = artifact.getFile().toURI().toURL();
                final ClassRealm realm = descriptor.getClassRealm();
                realm.addURL(url);
            }
            catch (MalformedURLException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

答案 4 :(得分:0)

没关系,我们需要制作自己的类加载器 Custom Classloaders