为什么手动连接 OSGi 服务不是一个好主意?
Why is it a bad idea to manually wire OSGi services?
为了使某些服务实现优于其他实现,我编写了 java.util.ServiceLoader
的可定制版本(通过非 OSGi 代码的首选项文件向实现添加优先级和 enabled/disabled 标志)。
客户很高兴并希望对 OSGi 服务实现进行相同的定制。
设计的解决方案基于调用 getServiceReferences(Class<S> clazz, String filter)
on BundleContext
并使用 null
过滤器检索所有实现。
然而,在如此低的级别上摆弄 OSGi 会留下不好的味道。有很多样板代码(例如 BundleActivator
的强制子类型),所使用的方法也会阻碍向声明式服务和某些时间点的平滑升级。
我也读到了 SERVICE_RANKING
属性,但是与上述方法的首选项文件相比,它的缺点是每个实现都设置了自己的排名 属性 并且它是之后无法更改排名。
所以我的问题是:反对这种低级方法的好理由是什么?为什么应该改用声明式服务?
OSGi 的核心是一个动态环境。捆绑包和服务可以随时来来去去(理论上)。所以应对这种环境的唯一方法是对变化做出反应,而不是等待事情发生。
例如,声明性服务组件将在其所有强制性服务都存在后出现,如果一个消失则消失。
基于服务加载器或类似的解决方案将主动获取可用的服务,如果此类服务是强制性的,那么您将不得不阻塞直到它可用。这很容易导致应用程序出现死锁。
当然,在实践中,应用程序通常不是那么动态。在大多数情况下,这只会影响应用程序的启动。所以在很多情况下,阻塞行为可以起作用,但它会产生一个本质上脆弱的应用程序。
另一方面,如果您的应用程序需要 运行 OSGi 内部和外部的问题,那么 DS 是有问题的,因为它依赖于存在的 OSGi。
典型的例子是 Aapache CXF 和 Apache Camel。两者都不使用 DS,而是为在 OSGi 中的使用发明了不同的抽象,因此两者有时在 OSGi 中都会出现问题。仍然很难改进这一点,因为他们也需要在 OSGi 之外工作。
为了使某些服务实现优于其他实现,我编写了 java.util.ServiceLoader
的可定制版本(通过非 OSGi 代码的首选项文件向实现添加优先级和 enabled/disabled 标志)。
客户很高兴并希望对 OSGi 服务实现进行相同的定制。
设计的解决方案基于调用 getServiceReferences(Class<S> clazz, String filter)
on BundleContext
并使用 null
过滤器检索所有实现。
然而,在如此低的级别上摆弄 OSGi 会留下不好的味道。有很多样板代码(例如 BundleActivator
的强制子类型),所使用的方法也会阻碍向声明式服务和某些时间点的平滑升级。
我也读到了 SERVICE_RANKING
属性,但是与上述方法的首选项文件相比,它的缺点是每个实现都设置了自己的排名 属性 并且它是之后无法更改排名。
所以我的问题是:反对这种低级方法的好理由是什么?为什么应该改用声明式服务?
OSGi 的核心是一个动态环境。捆绑包和服务可以随时来来去去(理论上)。所以应对这种环境的唯一方法是对变化做出反应,而不是等待事情发生。
例如,声明性服务组件将在其所有强制性服务都存在后出现,如果一个消失则消失。 基于服务加载器或类似的解决方案将主动获取可用的服务,如果此类服务是强制性的,那么您将不得不阻塞直到它可用。这很容易导致应用程序出现死锁。
当然,在实践中,应用程序通常不是那么动态。在大多数情况下,这只会影响应用程序的启动。所以在很多情况下,阻塞行为可以起作用,但它会产生一个本质上脆弱的应用程序。
另一方面,如果您的应用程序需要 运行 OSGi 内部和外部的问题,那么 DS 是有问题的,因为它依赖于存在的 OSGi。 典型的例子是 Aapache CXF 和 Apache Camel。两者都不使用 DS,而是为在 OSGi 中的使用发明了不同的抽象,因此两者有时在 OSGi 中都会出现问题。仍然很难改进这一点,因为他们也需要在 OSGi 之外工作。