Как избежать проблем с загрузкой классов с MyBatis в среде OSGI?
Я работаю над Eclipse 3.7 RCP-приложением с несколькими модулями. Модуль A представляет собой набор библиотек, включая mybatis-3.2.2.jar. Модуль B зависит от модуля A (Require-Bundle в manifest.mf) и имеет код, который использует MyBatis для доступа к данным в базе данных. Я экспортировал пакеты с классами Mapper и XML в модуле B и импортировал их в модуль A. Я создаю SqlSessionFactory в коде, и он работает нормально, если я добавляю все классы Mapper по имени, например
configuration.addMapper(MyMapper.class);
Однако, когда я пытаюсь добавить все Mappers в пакет:
configuration.addMappers(MyMapper.class.getPackage().getName());
MyBatis их не видит.
Я попытался изменить загрузчик классов по умолчанию, но это не помогло.
Resources.setDefaultClassLoader(this.getClass().getClassLoader());
Я подозреваю, что проблема связана с видимостью классов в среде OSGI. Если это так, есть ли способы исправить это в приложении?
3 ответа
Ты пытался
Resources.setDefaultClassLoader(Activator.class.getClassLoader())
, Я думаю, что будет использовать загрузчик класса OSGi для пакета. Надеюсь, это поможет.
Я столкнулся с подобной проблемой в Spring Data JPA в среде Felix OSGi. В этом случае я смог переопределить класс фабрики и добавить это в методы-нарушители:
ClassLoader pre = Thread.currentThread().getContextClassLoader();
try {
Thread.currentThread().setContextClassLoader(context.getClassLoader());
// add mappers here or call super method
} finally {
Thread.currentThread().setContextClassLoader(pre);
}
В этом случае "контекст" был контекстом Spring, но вы должны иметь возможность получить загрузчик классов модуля B из BundleWiring.
Bundle bundle; //get this by symbolic name if you don't have a reference
BundleWiring bundleWiring = bundle.adapt(BundleWiring.class);
bundleWiring.getClassLoader();
Надеемся, что метод addMappers не нуждается в доступе к загрузчику классов модуля A в одном вызове. Если это так, то вы не сможете сделать ничего, если не найдёте способ расширить и внедрить другой класс Configuration или MapperRegistry.
configuration.addMappers использует собственный ResolverUtil, который использует загрузчик класса контекста Thread. (По крайней мере, в mybatis3).
Лучше всего было бы написать свой собственный код сканирования и напрямую использовать addMapper. Ниже приведены мои ссылки и примеры:
РЕДАКТИРОВАТЬ: Вот некоторые для mybatis 3.2.2
То же самое относится, однако.