Maven插件:如何获得与运行测试时相同的类加载器访问权限?

huangapple go评论143阅读模式
英文:

Maven plugin: get access to the "same classloader" as when running tests?

问题

我正在尝试开发一个Maven插件,用于查找特定的类并为它们生成特定的文档。
我已经构建了一个用作单元测试的POC。现在我正试图将其转换为一个Maven插件。

测试代码可以访问项目的类以及任何依赖项的类。
我想在我的Maven插件中有一个"相同的类加载器"(或具有相同访问权限的类加载器)可用。

这是否可行?

获取对项目类的访问权限

创建一个包含项目类的类加载器是可行的:

@Mojo(name = "tao-generator", defaultPhase = LifecyclePhase.INSTALL)
public class TaoGeneratorMojo extends AbstractMojo {

    @Parameter(defaultValue = "${project}", required = true, readonly = true)
    MavenProject project;

    ...

    @SneakyThrows
    private ClassLoader getClassLoader(MavenProject project) {
        List<URL> runtimeUrls = new ArrayList<>();
        List<String> runtimeClasspathElements = project.getRuntimeClasspathElements();
        for (int i = 0; i < runtimeClasspathElements.size(); i++) {
            String element = runtimeClasspathElements.get(i);
            runtimeUrls.add(new File(element).toURI().toURL());
        }

        URL[] array = new URL[runtimeUrls.size()];
        array = runtimeUrls.toArray(array);

        return new URLClassLoader(array,
                Thread.currentThread().getContextClassLoader());
    }

获取对依赖项类的访问权限

我还没有弄清楚如何创建一个具有对依赖项类的访问权限的类加载器。我可以使用类似的技术,从MavenProject project开始吗?

另一个角度:从一个庞大的Spring Boot JAR加载类

我还尝试过直接从生成的庞大的Spring Boot JAR中加载类。这不适用于简单的URLClassLoader,因为该类加载器无法加载嵌套JAR中的类。也许这可以成为另一个使其工作的切入点的起点?

英文:

I'm trying to develop a Maven plugin that looks for certain classes and generates specific documentation for them.
I've built a POC as a unit test. I'm trying to convert that now to a Maven plugin.

The test code has access to the classes of the project + the classes of any dependency.
I'd like to have that "same classloader" (or a classloader with the same access) available in my Maven plugin.

Is this possible?

Getting access to the project classes

Creating a classloader that contains the classes of the project is doable:

@Mojo(name = &quot;tao-generator&quot;, defaultPhase = LifecyclePhase.INSTALL)
public class TaoGeneratorMojo extends AbstractMojo {

    @Parameter(defaultValue = &quot;${project}&quot;, required = true, readonly = true)
    MavenProject project;

    ...

    @SneakyThrows
    private ClassLoader getClassLoader(MavenProject project) {
        List&lt;URL&gt; runtimeUrls = new ArrayList&lt;&gt;();
        List&lt;String&gt; runtimeClasspathElements = project.getRuntimeClasspathElements();
        for (int i = 0; i &lt; runtimeClasspathElements.size(); i++) {
            String element = runtimeClasspathElements.get(i);
            runtimeUrls.add(new File(element).toURI().toURL());
        }

        URL[] array = new URL[runtimeUrls.size()];
        array = runtimeUrls.toArray(array);

        return new URLClassLoader(array,
                Thread.currentThread().getContextClassLoader());
    }

Getting access to the dependencies' classes

I haven't figured out how to create a classloader that has access to the dependencies classes. Can I use a similar technique, starting from MavenProject project?

Another angle: loading classes from a fat Spring Boot jar

I've also tried to load the classes directly from the generated fat Spring Boot jar. That doesn't work with a simple URLClassLoader, since that classloader isn't able to load classes from nested jars. Maybe this could be the starting point of another angle to make this work?

答案1

得分: 1

你可以通过调用 project.getArtifacts() 来访问依赖项。根据它的 javadoc:

该项目拥有的所有依赖项,包括传递性依赖项。内容是懒加载的,因此根据运行了哪些阶段,某些范围内的依赖项可能不会被包括。例如,如果只运行了编译阶段,范围为测试的依赖项将不会被包括。

你可以在 @Mojo 上使用属性来控制可用的依赖项。具体来说,你需要同时设置 requiresDependencyResolutionrequiresDependencyCollectionResolutionScope.TEST

英文:

You can access the dependencies by calling project.getArtifacts(). From its javadoc:

> All dependencies that this project has, including transitive ones. Contents are lazily populated, so depending on what phases have run dependencies in some scopes won't be included. eg. if only compile phase has run, dependencies with scope test won't be included.

You can use attributes on @Mojo to control the dependencies that are available. Specifically, you need to set both requiresDependencyResolution and requiresDependencyCollection to ResolutionScope.TEST.

huangapple
  • 本文由 发表于 2023年3月9日 17:36:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/75682740.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定