执行这些 hack 的标准方法是使用 OSGi 核心框架中的服务挂钩。这些挂钩允许您从一个或多个捆绑包的视图中删除一项服务。然后,您可以注册另一个服务来代理第一个服务,并且该服务不会从捆绑包的视图中删除。
现存的:
+----------+ +----------+
| register |------<|------| using |
+----------+ +----------+
Proxied
+----------+ hide +----------+
| register |------<|-+--X-| using |---|>---+ proxied
+----------+ | +----------+ |
| |
| +----------+ |
+----| manager |--------+
+----------+
虽然一开始有点奇怪,但这种“从视图中删除”功能允许您详细控制捆绑包暴露的服务,同时保持整体复杂性最小。请参阅 OSGi 5.0.0 Core 中的第 55 章。第 55.3.1 节详细介绍了这种代理。
<soapbox>
我称这些东西为 hack,因为这种方式的代理具有较差的运行时时间排序质量。如果您的管理器捆绑包(隐藏并创建代理的捆绑包)晚于使用该服务的捆绑包启动,那么您就会遇到麻烦,因为使用捆绑包暂时暴露给非代理服务。
尽管有多种方法可以解决开始排序这个问题,但它们基本上都很糟糕,因为您现在有一个未声明的(排序)依赖项。因此,最好确保使用代理的包具有特殊的依赖性,例如另一种服务类型或特殊的服务属性。由于依赖性是显式的,因此您不必再担心顺序,时间依赖性现在已成为一个普通的服务依赖性问题,DS 和 OSGi 中的其他服务管理器可以很好地处理该问题。
使用属性/其他类型进行代理
+----------+ +----------+ proxied=true
| register | | using |---|>---+
+----------+ +----------+ |
| |
| +----------+ |
+-----------<|------| manager |--------+
+----------+
显然,您不想修改注册服务的包或使用该服务的包,因为这会破坏可重用方面的整个想法。注册/使用包的程序员应该幸福地不知道经理的计划。那么如何在 using 包上设置过滤器呢?
如果您使用声明式服务 (DS),那么您很幸运!使用 DS,您可以通过配置管理使用“目标”对服务引用设置过滤器。配置属性。因此,管理器包看到要代理的服务,它会注册具有特殊属性的第二个服务(例如“proxied=true”)。然后,使用的包有一个通过配置管理 DS 的目标引用属性设置的过滤器,如“(proxied=*)”。
</soapbox>