OSGi环境下ServiceLoader.load失效及SPI Fly与openstack4j集成问题咨询
针对你遇到的OSGi环境下ServiceLoader.load找不到实现类,以及需要用SPIFly处理openstack4j相关类的问题,我整理了几个关键的解决步骤:
优先确保SPIFly动态Bundle启动顺序
由于你的openstack4j-core、openstack4j-httpclient和org.apache.aries.spifly.dynamic.bundle都在同一个ZIP里,且是系统启动后才加载的,一定要让SPIFly的动态Bundle先于openstack4j的两个Bundle启动。你可以在ZIP的启动配置里调整启动优先级,把SPIFly动态Bundle设为最高优先级的启动项,避免因为启动顺序导致编织时机错过。显式配置SPIFly编织目标类
要让SPIFly处理org.openstack4j.core.transport.HttpExecutorService,有两种可行方式:- 修改Bundle Manifest:如果能调整openstack4j-core的
MANIFEST.MF,添加指令SPI-Fly-Classes: org.openstack4j.core.transport.HttpExecutorService,直接告诉SPIFly这个类需要被编织处理。 - 动态编织命令:利用SPIFly动态Bundle的能力,在openstack4j Bundle启动前,通过OSGi控制台执行以下命令:
这个命令会触发SPIFly对指定Bundle里的目标类进行动态编织。spi:weave org.openstack4j.core org.openstack4j.core.transport.HttpExecutorService
- 修改Bundle Manifest:如果能调整openstack4j-core的
修正ServiceLoader的调用方式
OSGi的类加载隔离机制会导致原生ServiceLoader.load失效,建议改用SPIFly提供的org.apache.aries.spifly.ServiceLoader替代原生实现;如果必须用原生方法,要确保调用时使用目标接口所在Bundle的类加载器,示例代码如下:ServiceLoader<HttpExecutorService> loader = ServiceLoader.load( HttpExecutorService.class, HttpExecutorService.class.getClassLoader() );检查Bundle依赖配置
确保openstack4j-core和openstack4j-httpclient的MANIFEST.MF里正确声明了对SPIFly的依赖,比如添加:Require-Bundle: org.apache.aries.spifly.dynamic.bundle; resolution:=optional或者通过Import-Package导入SPIFly相关包:
Import-Package: org.apache.aries.spifly; version="[1.0.0,2.0.0)"排查类加载隔离问题
确认openstack4j-httpclient中HttpExecutorService的实现类所在包已经被正确导出,且openstack4j-core已经导入该包;同时要保证SPIFly的类加载器能够访问到这些类,没有被OSGi的类加载隔离规则阻挡。
内容的提问来源于stack exchange,提问作者JozinSBazin

