这个问题现在要交给赏金了!解决此问题的第一个答案获胜。
所以我最近发现 OSGI 中的包不是 100% 相互隔离的,尤其是当你的包共享一个包含单例的公共包时,这可能导致两个不相关的包覆盖单例。这个问题已经在 CXF 库中体现出来了。让我举一个详细的例子来说明正在发生的事情:
我们在 FuseESB ServiceMix(一个 osgi 平台)中有包 A、B 和共享包 CXF。CXF 的 Bus 类是一个单例,因为 OSGI 每个包都有一个类加载器,它会与使用 CXF 的所有其他包共享这个单例。所以我似乎无法为包 A 和包 B 创建不同的总线,这很重要,因为包 A 应该使用 SSL,而包 B 不应该使用 SSL。这更令人沮丧,因为 bundle A 和 bundle B 除了必须一起部署在同一个 ServiceMix 上之外,彼此没有任何关系。
现在我已经解决这个问题一段时间了(1-2 个月),我已经阅读了很多不同的解决方案。然而问题是很多解决方案都要求我完全控制源代码,而在这种情况下我不需要。我正在创建的 Bundle A 使用了一些专有的第三方非 osgi 库,称为 Xenara,它使用 CXF。出于我无法控制的商业原因,我必须使用这个第三方库。幸运的是,我确实可以访问该库使用的 CXF spring bean 文件。
我对解决这个问题的猜测是,我需要一些方法,以便包 A 可以使用它自己的个人 CXF 实例,或者至少让它实例化不与其他包共享的 CXF 总线。以下是我尝试或考虑过的方法:
我将 CXF 嵌入到包 A 中,但不幸的是,类加载器一直从包 A 外部获取 CXF,而不是查看类路径。从来没有想过如何强制它在包 A 之外搜索之前先在包 A 中搜索 CXF。
有人建议将捆绑包 A 变成一项服务。我认为存在一些误解,人们认为单例在 A 中而不是在 CXF 中。无论如何我尝试了它并没有解决问题。CXF 总线仍然在包 A 和 B 之间共享。
覆盖类加载,以便包 A 使用不同的类加载器来加载 CXF 类。我不完全理解这其中的逻辑,但我确信这将是非常棘手的,因为使用了一个 spring bean 来创建 CXF 总线和 http-conduit。请参阅下面的 (4) 以获得更好的想法。
在 CXF 中,有一种方法可以为给定的线程上下文设置 CXF 总线和 http-conduit。我真的很想使用这个解决方案,但我不知道如何将 CXF bean 文件转换为等效的 java 代码。下面提供了 CXF spring bean 文件。请注意,我无权使用此 http-conduit 访问源代码,这就是为什么我没有使用“使用 Java 代码”的此链接中显示的示例,因为我无权访问 SOAPService、wsdl , ETC...
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" /> <property name="searchSystemEnvironment" value="true" /> <property name="ignoreUnresolvablePlaceholders" value="true" /> </bean> <cxf:bus> <cxf:outInterceptors> <bean class="com.xenara.messaging.security.IdentityAssertingOutInterceptor" scope="singleton" /> </cxf:outInterceptors> <cxf:features> <wsa:addressing xmlns:wsa="http://cxf.apache.org/ws/addressing"/> </cxf:features> </cxf:bus> <http-conf:conduit name="*.http-conduit"> <http-conf:client AllowChunking="false" Connection="Keep-Alive" /> <http-conf:tlsClientParameters disableCNCheck="true" secureSocketProtocol="TLS"> <sec:keyManagers keyPassword="${javax.net.ssl.keyStorePassword}"> <sec:keyStore type="JKS" password="${javax.net.ssl.keyStorePassword}" file="${javax.net.ssl.keyStore}" /> </sec:keyManagers> <sec:trustManagers> <sec:keyStore type="JKS" password="${javax.net.ssl.trustStorePassword}" file="${javax.net.ssl.trustStore}" /> </sec:trustManagers> <sec:cipherSuitesFilter> <sec:include>SSL_RSA_WITH_3DES_EDE_CBC_SHA</sec:include> ... </sec:cipherSuitesFilter> </http-conf:tlsClientParameters> </http-conf:conduit>