81 подписчик
🖥 Глубокое погружение в Java: рефлексия и загрузчик классов. Часть 3
Практический пример: добавление функциональности плагина в Java-приложение
Плагины — это небольшие программы, которые могут быть включены в работающее приложение для расширения его функциональности.
Рассмотрим редактор кода Visual Studio Code, который помогает в таких задачах разработки, как отладка, тестирование кода и контроль версий. Кроме того, он поставляется на рынок с тысячами расширений, которые могут загружать пользователи. Расширения варьируются от самых необходимых, таких как редактирование кода для определенного языка программирования, до премиальных (например, Prettier для обеспечения единого стиля кода и Better Comments, которое создает цветные комментарии к коду). Visual Studio Code предоставляет эти расширения по технологии plug-and-play.
Хотя VS code написан не на Java, идея архитектуры плагинов та же — необходимость расширения системы или подключения новой функциональности во время выполнения. Функциональность плагинов в Java-приложении реализуется с помощью рефлексии и загрузчиков классов. Создать простой плагин можно в три этапа:
1. Определение интерфейса плагина.
2. Определение загрузчика классов плагина.
3. Определение протокола для установки и запуска плагинов в системе.
На 1-м этапе должен быть определен единый интерфейс, через который приложение может запускать любой плагин.
public interface Plugin {
// возвращает имя плагина
public String getPluginName();
// запускает функциональность плагина
public void run();
// используется для настройки плагина, если это необходимо
// возвращает true/false при успешной/неудавшейся настройке
public boolean configure(Object configuration);
}
Все плагины должны иметь класс, реализующий этот интерфейс. Данный интерфейс выполняет роль маркера. При загрузке плагинов приложение рефлексивно проверяет классы в поисках класса, реализующего этот интерфейс. Он содержит метод run(), который является точкой входа для запуска плагина. В качестве альтернативы можно использовать аннотации для обозначения функции запуска плагина, аналогично примеру JUnit.
На 2-м этапе для загрузки классов плагина определяется специальный загрузчик классов. Это требуется по многим причинам.
▪️Класс однозначно идентифицируется по его имени и загрузчику классов. Загрузка плагина с помощью специального загрузчика классов создает уникальное пространство имен для классов плагина. Это предотвращает возникновение конфликтов между классами приложения и классами плагина. Например, если и приложение, и плагин определили класс с именем Foo, то JVM будет знать, как их различать, поскольку класс Foo приложения был загружен Application ClassLoader, а класс Foo плагина — специализированным загрузчиком классов, и каждый из них будет иметь свой объект Class.
▪️Не следует полностью доверять безопасность приложения коду внешнего плагина. Он может содержать непроверенный, ошибочный или вредоносный код. Наличие отдельного загрузчика классов, загружающего классы плагинов, позволяет наложить ограничения по безопасности на классы плагинов (подробнее об этом здесь).
Будет удобнее определить специальный путь для всего кода плагина. Загрузчик классов плагина будет искать файлы классов по этому пути, и его можно определить следующим образом:
2 минуты
21 ноября 2023