我正在制作一个在测试阶段运行的 Maven 插件,在使用我的插件的项目的 pom.xml 配置中,我正在设置一个类规范名称,我想用它来从我的插件运行该类,基本上我我正在寻找一种方法,可以从我的插件中动态加载项目中的类。
Class clazz = Class.forName("... class from pom.xml ...")
当我运行它时,我收到预期的“ClassNotFoundException”,似乎类加载器不相同或未共享。
有办法吗?就像从项目中捕获类加载器或通过依赖项注入到我的插件中接收它一样?最好的方法是什么?
我们可以使用mojo中的Hibernate实现作为参考来制作:
private ClassLoader getClassLoader(MavenProject project)
{
try
{
List 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 ) ).toURL();
}
return new URLClassLoader( urls, this.getClass().getClassLoader() );
}
catch ( Exception e )
{
getLog().debug( "Couldn't get the classloader." );
return this.getClass().getClassLoader();
}
}
要捕获“项目”对象,我们可以使用mojo依赖注入:
/**
* Dependency injected
*/
@Parameter(defaultValue = "${project}")
public MavenProject project;
并使用它在项目类加载器中加载一些类:
getClassLoader(this.project).loadClass("com.somepackage.SomeClass")
我也在寻找这个答案。在 maven 的类加载指南页面(我花了一段时间才找到它)上面写着:
请注意,插件类加载器不包含 当前项目及其构建输出的依赖项。反而, 插件可以查询项目的编译、运行时和测试类路径 来自 MavenProject 与 mojo 注释的结合 Mojo API 规范中的 requireDependencyResolution。为了 例如,使用 @requiresDependencyResolution 运行时标记 mojo 使其能够查询当前项目的运行时类路径 它可以创建更多的类加载器。
当执行构建插件时,线程的上下文类加载器是 设置为插件类加载器。
因此,根据我的理解,文本是,首先您需要在 @Mojo 注释上添加
requiresDependencyResolution=ResolutionScope.RUNTIME
,然后编写自定义类加载器操作以从 Maven 插件访问和加载项目上所需的类。
@Mojo(name = "check", requiresDependencyResolution = ResolutionScope.RUNTIME)
public class MyMojo extends AbstractMojo {
...
@Override
public void execute() throws MojoExecutionException, MojoFailureException {
Class<?> clazz = getClassLoader().loadClass("SOME_CLASS_NAME");
// do whatever you want with the clazz, instantiate it, call its static methods, etc...
...
}
// Method courtesy from TabNine From Google Results.
private ClassLoader getClassLoader() {
ClassLoader classLoader = null;
try {
List<String> classpathElements = project.getRuntimeClasspathElements();
if (null == classpathElements) {
return Thread.currentThread().getContextClassLoader();
}
URL[] urls = new URL[classpathElements.size()];
for (int i = 0; i < classpathElements.size(); ++i) {
urls[i] = new File((String) classpathElements.get(i)).toURI().toURL();
}
classLoader = new URLClassLoader(urls, getClass().getClassLoader());
} catch (Exception e) {
e.printStackTrace();
}
return classLoader;
}
一些链接: