我们正在使用Karaf
和一些OSGI Blueprint services
来实现一个系统。
是否可以制作一种"BundleListener"
类型的包,当它出现在容器中时,用代理OSGI
装饰我们的包,以便引用这些服务的包将调用代理?Blueprint services
(我想这可以通过以某种方式在服务注册表中已经存在的服务前面添加代理,或者通过更改引用包获得的引用来实现 -ServiceTracker.addingService
样式)
我们正在使用Karaf
和一些OSGI Blueprint services
来实现一个系统。
是否可以制作一种"BundleListener"
类型的包,当它出现在容器中时,用代理OSGI
装饰我们的包,以便引用这些服务的包将调用代理?Blueprint services
(我想这可以通过以某种方式在服务注册表中已经存在的服务前面添加代理,或者通过更改引用包获得的引用来实现 -ServiceTracker.addingService
样式)
进行这些 hack 的标准方法是使用 OSGi 核心框架中的服务挂钩。挂钩允许您从一个或多个捆绑包的视图中删除服务。然后,您可以注册另一个服务来代理第一个服务并且不会从包的视图中删除。
现存的:
+----------+ +----------+
| register |------<|------| using |
+----------+ +----------+
代理
+----------+ hide +----------+
| register |------<|-+--X-| using |---|>---+ proxied
+----------+ | +----------+ |
| |
| +----------+ |
+----| manager |--------+
+----------+
虽然一开始有点奇怪,但这种“从视图中移除”功能允许您详细控制捆绑包所暴露的服务,同时保持整体复杂性最小。请参阅 OSGi 5.0.0 核心中的第 55 章。第 55.3.1 节详细介绍了此代理。
<soapbox>
我将这些东西称为 hack,因为这种方式的代理具有较差的运行时时间排序质量。如果您的管理器包(隐藏和创建代理的那个)启动晚于使用该服务的包,那么您就会遇到麻烦,因为使用包暂时暴露给非代理服务。
虽然有一些方法可以解决开始订购这个问题,但它们基本上都很糟糕,因为你现在有一个未声明的(订购)依赖关系。因此,最好确保使用代理的包具有特殊的依赖关系,例如另一种服务类型或特殊的服务属性。由于依赖是显式的,您不必再担心排序,时间依赖现在已经成为一个普通的服务依赖问题,DS 和 OSGi 中的其他服务管理器可以很好地处理。
使用属性/其他类型进行代理
+----------+ +----------+ proxied=true
| register | | using |---|>---+
+----------+ +----------+ |
| |
| +----------+ |
+-----------<|------| manager |--------+
+----------+
您显然不想修改注册服务的包或使用服务的包,因为这会扼杀可重用方面的整个想法。注册/使用包的程序员应该很高兴地不知道经理的计划。那么如何在使用包上设置过滤器?
如果您使用声明式服务 (DS),那么您很幸运!使用 DS,您可以通过 Configuration Admin 使用“目标”对服务引用设置过滤器。配置属性。因此,管理器捆绑包看到要代理的服务,它使用特殊属性(例如,'proxied=true')注册第二个服务。然后,使用包通过 Configuration Admin DS 的目标引用属性设置了一个过滤器,例如“(proxied=*)”。
</soapbox>
虽然没有作为代理实现,但蓝图拦截器可能会做你想做的事;您可以在调用原始 bean 之前或之后拦截方法调用。我认为无论如何这就是您对代理所做的事情。Karaf 中的 Aries Blueprint 实现绝对应该支持拦截器。但是,我在 Aries 源代码本身之外找不到好的文档或示例,这使得这个答案没有我希望的那么有用!