【问题标题】:scanning java classpath in the maven plugin在 maven 插件中扫描 java 类路径
【发布时间】:2012-01-26 16:06:13
【问题描述】:

我想做的是编写一些 Maven 插件,它扫描应用程序类以查找特定接口的实现(它也可能是带有一些注释的类)并根据结果生成一些代码。我已经成功实现了在 generate-sources 阶段运行的插件,并将源代码写入 generate-sources 目录。

问题在于扫描类路径以查找带有一些注释的特定接口实现/类。 我正在使用Reflections 库通过以下方式扫描类:

private Set<Class< ? extends MyInterface >> scan(final String packageName) {
  final Reflections reflections = new Reflections(packageName);  
  return reflections.getSubTypesOf(MyInterface.class);
}

不幸的是,此方法返回空集。当我在扩展 org.apache.maven.plugin.AbstractMojo 的类中打印我的类路径(我在其中使用 Reflections)时,我得到以下结果:

/home/pd5108/apache-maven-2.2.1/boot/classworlds-1.1.jar

我想使用反射找到的类存在于依赖 JAR 以及配置插件的模块中。查看打印出来的类路径,似乎此时(生成源阶段)在 maven 中定义的依赖项在类路径上都还不可用 - 可能它们会在下一阶段添加。真的吗?我可以使用其他方法吗?

这是类路径的打印方式:

URL[] urls = ((URLClassLoader)sysClassLoader).getURLs();

for(int i=0; i< urls.length; i++) {
  System.out.println(urls[i].getFile());
}

【问题讨论】:

    标签: java reflection maven-2 classpath maven-plugin


    【解决方案1】:

    必需的 MOJO 类字段:

        /**
        * The project currently being built.
        *
        * @parameter expression="${project}"
        * @readonly
        * @required
        */
        private MavenProject project;
    
        /** @parameter expression="${localRepository}" */
        protected ArtifactRepository m_localRepository;
    
        /**@parameter default-value="${localRepository}" */
        private org.apache.maven.artifact.repository.ArtifactRepository
            localRepository;
    
        /** @parameter default-value="${project.remoteArtifactRepositories}" */
        private java.util.List remoteRepositories;
    
        /** @component */
        private org.apache.maven.artifact.factory.ArtifactFactory artifactFactory;
    
        /** @component */
        private org.apache.maven.artifact.resolver.ArtifactResolver resolver;
    

    所有依赖JAR的解析:

     final List<Dependency> dependencies = project.getDependencies();
    
        for (Dependency d : dependencies) {
    
            final Artifact artifact =
                artifactFactory.createArtifactWithClassifier(d.getGroupId(),
                    d.getArtifactId(), d.getVersion(), d.getType(),
                    d.getClassifier());
    
            try {
                resolver.resolve(artifact, remoteRepositories,
                        localRepository );
            } catch (ArtifactResolutionException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ArtifactNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    
            File artifactFile = artifact.getFile();
            System.out.println(artifactFile.getAbsolutePath());
        }
    

    现在我们需要使用反射 API 扫描这些 JAR 以寻找合适的类。 在这一点上,我认为没有其他办法,因为我在generate-sources 阶段工作,并且尚未计算下一阶段的工件值。

    【讨论】:

      【解决方案2】:

      &lt;dependencies&gt; 部分定义了工件依赖项,&lt;plugin&gt;&lt;dependencies&gt; 定义了插件依赖项。

      插件依赖项被添加到类路径中,而我不确定工件依赖项。您是否尝试在 &lt;plugin&gt;&lt;dependencies&gt; 下添加插件依赖项?

      【讨论】:

      • 根据您的建议,我添加了一个“插件依赖项”,现在它在打印出来的类路径下不可见(奇怪),但反射库检测到正确实现 MyInterface 的类!有什么方法可以在插件依赖项中包含工件依赖项?我很想避免整个部分的复制粘贴:/
      • @PiotrekDe 也许您可以创建一个包含所有必要依赖项的 jar 项目,您可以将其用作 POM 和插件的依赖项。我不确定这是否值得痛苦......
      【解决方案3】:

      仅让插件配置列出您想要生成代码的类可能会更快/更安全/更容易。然后你只需将它添加到 pom 中就可以了。不需要反射,它肯定会加速插件的运行。

      【讨论】:

      • 这是我认为作为最后手段的选项...由于我有很多实现此接口的类,并且在代码生成中考虑了所有类,因此我想避免输入所有类'静态地'。此外,这些类经常被添加/删除。
      • 您总是可以有一个 shell 脚本来执行类似 grep all java files for "implements X" 的操作,然后解析出类名并构建它们的属性文件。然后让您的插件使用该属性文件来了解要为哪些类生成额外代码。如果你不在unix上,你可以在java中模拟grep,但它会慢得多。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-05-28
      • 2022-01-22
      • 1970-01-01
      • 2015-05-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多