我有一个 Java 应用程序(应部署为可执行 JAR),它采用 JSON 文件作为输入,如下所示:
"appConfig": {
"fizzClass": "com.me.myorg.FizzImpl"
// Lots of other configs
}
该配置允许用户指定在运行时使用什么fizzClass
(对于某物,具体是什么并不重要)。问题是,我希望这个应用程序接受插件;也就是说,我可以(在运行时动态地)将 JAR 添加到应用程序,其中可能会打包其他 Fizz 实现,然后用户可以在其配置文件中指定这些新可用的 impl。例如,也许我的应用程序中只有 public class FizzImpl Implements Fizz
。现在假设有人开发了一个插件,foo-plugin.jar
,其中包含公共(public)类 FooFizz 实现了 Fizz
。现在,在作为插件部署到我的应用程序后,最终用户可以向应用程序传递以下配置:
"appConfig": {
"fizzClass": "com.some.other.foo.FooFizz"
// Lots of other configs
}
...没有得到 ClassNotFoundException
等。因为现在 FooFizz
位于应用程序的运行时类路径上。
OSGi 感觉是这个问题的完美解决方案。我正在尝试了解 Apache Felix 的架构。我的理解是,我将应用程序部署为 JAR,但包含 Felix JAR 作为其依赖项,这使我可以访问插件架构。然后我必须要求插件开发人员将他们的 JAR 打包为 OSGi 包。因此,首先,如果这些陈述有任何误导或不正确的地方,请首先纠正我对 Java JAR 如何利用 Felix OSGi 运行时的理解!
假设我的理解或多或少是正确的,我的问题是:为了为我的应用程序开发插件,我是否只遵循打包 bundle 的正常说明,或者是否有特殊的“技巧”利用 Felix 的插件架构?
最佳答案
在 OSGi 中实现插件架构的一个好方法是使用 OSGi 服务。您可以将 Fizz 接口(interface)以及构成 API 的所有其他内容打包到一个包中。然后,您为 FizzImpl 使用第二个包并使用激活器或例如将 impl 实例发布为 OSGi 服务的蓝图。 最后一部分是您的主应用程序,它需要绑定(bind)服务并使用接口(interface)调用服务。 所以这将是您的默认设置。
然后有人可以使用替代实现创建另一个 bundle ,并将其发布为服务。为了区分这两种服务,您可以在发布服务时指定属性。
然后在您的主应用程序中,您可以使用可配置的过滤器来绑定(bind)与过滤器匹配的服务。所以你可以通过改变过滤器来切换impl。
我在 cxf xkms 中使用了这种方法来为 xkms 实现一个基于 ldap 的后端,该后端可以切换为其他内容。 这是 ldap impl 的蓝图文件: https://github.com/apache/cxf/blob/master/services/xkms/xkms-x509-repo-ldap/src/main/resources/OSGI-INF/blueprint/blueprint.xml
这是主应用程序的蓝图 xml: https://github.com/apache/cxf/blob/master/services/xkms/xkms-osgi/src/main/resources/OSGI-INF/blueprint/blueprint.xml
最后一部分是使用配置过滤器绑定(bind)服务的 java 代码: https://github.com/apache/cxf/blob/master/services/xkms/xkms-service/src/main/java/org/apache/cxf/xkms/service/CertificateRepoProxyFactory.java
关于java - OSGi解决可插拔架构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24436921/