我正在阅读一本关于使用OSGi的模块化应用程序的书,我正在构建一些原型等等。书中有一点,作者说应该避免使用低级服务API 来注册服务和依赖管理,并鼓励他的读者使用依赖框架(例如依赖经理)。
这很好,除了作者没有说为什么?这一点,或者至少我没有得到任何相当重要的理由。所以,我有以下代码:
httpService = context.getService(context.getServiceReference(HttpService.class));
使用低级API获取HttpService
服务的实例,并且使用DependencyManager有这种方法:
dependencyManager.add(createComponent()
.setImplementation(ResourceRegistration.class)
.add(createServiceDependency()
.setService(HttpService.class)
.setRequired(true)));
将SericeDependency设置为类ResoureRegistration
,否则我必须按上面所述获得服务(使用低级服务API)。
现在,不考虑为了在代码中注入相同的依赖项而必须编写多少行,是否有相当大的理由不(或至少避免)使用低级服务API?
我不得不说,我正在使用低级API并避免使用(我认为)不必要的额外框架,以避免使用一堆框架和不必要的捆绑包制作“胖”最终版本,其中有些人说这些都是必需的,因为它们可以通过在部署中承担更多黑盒捆绑包而为您节省几行代码。
作者还指出,使用低级服务API “我们必须自己检查注销服务”。我的另一个问题是,通过实施依赖框架,我们会避免这种检查吗?
感谢您的时间.-
答案 0 :(得分:2)
context.getService()的问题在于您可能无法使用您在更长时间内获得的服务对象。原因在于OSGi的动态。
如果发布服务的捆绑包已停止,则会取消注册该服务。服务取消注册后,您不应再使用它。在最坏的情况下,您仍然在服务对象上持有引用这一事实将使垃圾收集器无法清理已卸载的bundle的类加载器。更糟糕的是,如果您在(现在无效)服务上调用方法。将执行服务方法,但服务所需的资源甚至其类加载器现在可能无效。所以你会得到异常和内存泄漏。
如果你真的想使用低级API,那么你必须在需要服务之前不久做getService(),然后在asapService()之后执行。这非常不方便,并且使用OSGi调用污染您自己的代码。这就是为什么很少有人像这样使用API。
如果您想坚持使用OSGi API,可以使用ServiceTracker。它允许您始终使用getService()获取有效的服务对象,或者在服务出现时对其进行响应,并使用回调addsService和removedService消失。
依赖管理器,声明性服务和蓝图等框架为您管理这些动态。
例如,如果在具有强制@Reference的声明性服务中定义@Component,那么只有当所有需要的服务都存在时,您的整个组件才会出现,如果服务发生变化,您将获得注入的新服务。据我所知,依赖经理做了类似的事情。
蓝图的动态性稍差。它只会注入一次,但会注入一个始终指向有效服务的代理,如果没有,则会阻塞。
所有这一切都是为了保护您免受处理服务动态的复杂性。作为一个粗略的指导原则,如果您自己编写技术OSGi库或框架,我将只使用低级API,并且可能不依赖于添加的依赖项。对于业务应用程序,如果没有其中一个框架,就不应该工作。
答案 1 :(得分:1)
“Dependency Manager”只是众多组件框架中的一个。我到目前为止阅读的大多数文章,教程和代码示例都使用了声明式服务或蓝图,所以我得到的印象是Dependency Manager是较少使用的框架之一。但这并不一定很糟糕,如果它提供其他框架不具备的功能。
Dependency Manager的编程方法似乎接近低级API。它可能在某个地方有它的目的,但我还没有找到它。
大多数框架使用基于DI /注释的方法。您只需使用@Component
注释类,使用@Reference
(或getter / setter方法)注释属性,框架将处理从组件实例化到绑定和解除绑定服务的所有内容。访问服务就像这样:
@Reference
private MyService myService;
查看“声明性服务”,了解不复杂的框架。还有Blueprint和iPOJO。我认为对于更大的应用程序,您将需要一个框架来保持理智。还要记住,大多数框架在构建时都做了很多。我不认为他们是“胖子”。
httpService = context.getService(context.getServiceReference(HttpService.class));
这里的问题是,如果此时没有HttpService怎么办?当然,你可以检查一下 - 但是你怎么知道什么时候可用,所以你可以在以后注册你的servlet?您需要为此编写一个ServiceTracker,这很复杂且需要很多boilerplate code。
至少使用白板模式,将Servlet注册为服务,HttpService会在可用时发现它们。你可以通过使用bundle上下文在没有框架的情况下做到这一点。我认为使用框架仍然更容易,只需将@Service @Component
放在课堂前,而不是手工完成所有操作。