Ну, я попытался создать новый URLClassLoader и связать его с текущим ClassLoader.
@Override
public void execute() throws MojoExecutionException, MojoFailureException {
//a direct absolute path just for testning
chainClassLoader(new File("C:\\Users\\admin\\.m2\\repository\\message-plugin\\real-message\\1.0\\real-message-1.0.jar"));
Message message = null;
try {
Class<?> clazz = Class.forName(messageClass);
message = (Message) clazz.newInstance();
} catch (Exception e) {
getLog().error(e);
}
getLog().info(message.getMessage());
}
private void chainClassLoader(File file) throws Exception {
ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader();
URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{file.toURI().toURL()}, currentClassLoader);
Thread.currentThread().setContextClassLoader(urlClassLoader);
}
Но все же я получаю ClassNotFoundException.
Кроме того, как именно я могу «захватить зависимости проекта» с помощью @requiresDependencyResolution
?
EDIT:
Хорошо, я думаю, что понял. Иерархия ClassLoader в плагине выглядит следующим образом.
null
sun.misc.Launcher$ExtClassLoader
sun.misc.Launcher$AppClassLoader
null
org.codehaus.classworlds.RealmClassLoader
java.net.URLClassLoader // my chained classloader
Class.forName(clazz)
пытается найти клац, начиная с AppClassLoader
, который делегирует его родителю ExtClassLoader
. Но так как я добавил новый classpath к URLClassLoader
, который, по-видимому, находится в другой иерархии ClassLoader, я получаю ClassNotFoundException
.
Решение заключается не в использовании Class.forName(clazz)
, а в Thread.currentThread().getContextClassLoader().loadClass(clazz)
, потому что я приковал URLClassLoader
к ContextClassLoader
Нити.