Динамическая загрузка классов в OSGi

У меня есть целая куча модулей фреймворка, которые отлично работают на OSGi, все сервисы и компоненты находят друг друга и работают нормально.

Однако есть одна структура, которая делает некоторые динамические вещи в отношении классов. По сути, в какой-то момент вы даете ему имя класса, и он выполняет Class.forName(), а затем происходит магия отражения.

Это прекрасно работает при работе в стандартном jvm и использовании SPI для соединения фреймворков, но в OSGi это не работает, потому что, конечно, этот случайный класс «test.MyTest», к которому вы пытаетесь подойти через фреймворк, не виден указанному фреймворку.

Он выдаст «java.lang.ClassNotFoundException: test.MyTest не найден фреймворком».

Итак, мой вопрос: как я могу решить эту нехватку видимости для фреймворка, который должен видеть все? Import-Package: *?

ОБНОВЛЕНИЕ

Предполагая, что OSGi не сильно изменился с 2010 года в этом отношении, статья http://njbartlett.name/2010/08/30/osgi-readiness-loading-classes.html очень интересно. В настоящее время я добавил поддержку как для активно регистрируемых классов, так и для внедрения фабрики доменов через OSGi.

Кроме того, при разрешении по умолчанию в любом случае используется контекстный загрузчик классов, поэтому, если ничего не помогает, он будет использоваться для попытки загрузить класс.

ОБНОВЛЕНИЕ

Я также добавил поддержку предложенного DynamicImport-Package, что проще для небольших проектов.


person nablex    schedule 07.11.2014    source источник
comment
О каком фреймворке вы говорите? Есть ли у вас контроль над кодом?   -  person Christian Schneider    schedule 07.11.2014
comment
Да, это мой собственный фреймворк   -  person nablex    schedule 07.11.2014
comment
Тогда во что бы то ни стало избегайте Class.forName(). Смотрите мой обновленный ответ   -  person Christian Schneider    schedule 07.11.2014


Ответы (1)


Вы можете использовать DynamicImport-Package:*. Это позволит пакету видеть все классы. Проблема в том, что у вас нет реального контроля над тем, что именно раскрывается. Так что это обычно крайняя мера, а не рекомендуемый способ.

Сначала вы должны попытаться использовать Thread.currentThread().setContextClassLoader() и установить его в загрузчик классов класса, который вы предоставляете фреймворку. Иногда фреймворки также обращаются к этому загрузчику классов.

Еще лучший способ — найти в фреймворке метод, позволяющий предоставить пользовательский загрузчик классов.

Если у вас есть контроль над кодом, избегайте Class.forName(). Вместо этого позвольте пользователю либо предоставить вам объект класса вместо имени класса, либо позволить пользователю предоставить вам комбинацию имени класса и используемого загрузчика классов. Оба способа прекрасно работают как в OSGi, так и за его пределами.

person Christian Schneider    schedule 07.11.2014
comment
К сожалению, фреймворк на самом деле является реализацией фреймворка более высокого уровня и должен использовать строковый идентификатор для идентификации класса. - person nablex; 07.11.2014
comment
Хм, я не могу заставить DynamicImport-Package работать. Что-то особенное мне нужно сделать или просто установить это в манифесте? - person nablex; 07.11.2014
comment
Вы просто устанавливаете его в манифесте вашего фреймворка. Вам все равно нужно убедиться, что пакет, к которому вы хотите получить доступ, экспортирован. - person Christian Schneider; 07.11.2014
comment
Хех, теперь это работает, но не в сочетании с загрузчиком классов контекста потока (по крайней мере, в моем тесте). - person nablex; 07.11.2014
comment
загрузчик классов контекста потока работает только в том случае, если фреймворк также использует его. Так что в вашем случае это не поможет. - person Christian Schneider; 07.11.2014