Java :: classpath менеджмент во время выполнения
5 августа 2008 Разработка 3,638 1 | font-size: ↑ ↓
Постановка задачи
Необходимо дать возможность модифицировать classpath во время выполнения приложения. Это может понадобиться при разработке механизма управления аддонами (расширениями) приложения, в случае, когда JAR-файлы содержашие соответствующие классы нужно добавить в classpath в зависимости от конкретной конфигурации приложения либо еще каких-то условий, зависящих от бизнес-логики.
Решение
При помощи метода ClassLoader.getSystemClassLoader() можно получить системный загрузчик классов - екземпляр класса java.net.URLClassLoader. Он имеет метод addURL(java.net.URL), который, собственно, и определяет URLs которые будут использованы при необходимости загрузки того или иного класса во время выполнения приложения.
Небольшой нюанс лишь в том, что этот метод имеет спецификатор доступа protected, а значит вызвать его напрямую не получится.
На помощь приходит механизм отражения Java. Перед вызовом метода, нужно лишь сделать его доступным для вызова “извне” при помощи другого метода - setAccessible(boolean) класса java.lang.reflect.Method.
Код
Ниже следует пример кода, который добавляет к classpath’у URLs всех файлов внутри заданной директории с аддонами. В реальной ситуации, естественно, бизнес-логика этого процесса может быть значительно более комплексной.
package examples;
import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
/**
* @author kion
*
* Пример класса, модифицирующего classpath прямо во время выполнения.
*
*/
public class AddOnsLoader {
// директория, содержащая аддоны
private static final File ADDONS_DIR = new File("/path/to/dir/with/addons");
// префикс для URL локальных файлов
private static final String FILE_PROTOCOL_PREFIX = "file:";
public static void loadAddOns() throws Throwable {
// проверка существования директории с аддонами
if (ADDONS_DIR.isDirectory()) {
for (File file : ADDONS_DIR.listFiles()) {
// добавление каждого из найденых файлов к classpath
addClassPathURL(FILE_PROTOCOL_PREFIX + file.getAbsolutePath());
}
}
}
private static void addClassPathURL(String path) throws Throwable {
// URL файла для добавления к classpath
URL u = new URL(path);
// достаем системный загрузчик классов
URLClassLoader urlClassLoader =
(URLClassLoader) ClassLoader.getSystemClassLoader();
// используя механизм отражения,
// достаем метод для добавления URL к classpath
Class urlClass = URLClassLoader.class;
Method method = urlClass.getDeclaredMethod(
"addURL",
new Class[]{ URL.class });
// делаем метод доступным для вызова
method.setAccessible(true);
// вызываем метод системного загрузчика,
// передавая в качестве параметра
// URL файла для добавления к classpath
method.invoke(urlClassLoader, new Object[]{ u });
}
}









Один комментарий »
↓