【问题标题】:Can I inject proxies in front of Blueprint services published by other bundles?我可以在其他包发布的蓝图服务前注入代理吗?
【发布时间】:2013-04-26 19:53:17
【问题描述】:

我们正在使用Karaf 和一些OSGI Blueprint services 来实现一个系统。

是否可以创建一个"BundleListener" 类型的包,当它出现在OSGI 容器中时,用代理装饰我们的Blueprint services,以便引用这些服务的包将调用代理?

(我想这可以通过在服务注册表中已经存在的服务前面添加代理来实现,或者通过更改引用包获得的引用 - ServiceTracker.addingService 样式)

【问题讨论】:

    标签: java osgi blueprint-osgi


    【解决方案1】:

    进行这些 hack 的标准方法是使用 OSGi 核心框架中的服务挂钩。挂钩允许您从一个或多个捆绑包的视图中删除服务。然后,您可以注册另一个服务来代理第一个服务并且不会从包的视图中删除。

    现有:

      +----------+              +----------+
      | register |------<|------| using    |
      +----------+              +----------+
    

    代理

      +----------+         hide +----------+
      | register |------<|-+--X-| using    |---|>---+ proxied
      +----------+         |    +----------+        |
                           |                        |
                           |    +----------+        |
                           +----|  manager |--------+
                                +----------+
    

    虽然一开始有点奇怪,但这种“从视图中移除”功能允许您详细控制捆绑提供的服务,同时将整体复杂性保持在最低限度。请参阅 OSGi 5.0.0 核心中的第 55 章。第 55.3.1 节详细介绍了此代理。

    &lt;soapbox&gt;

    我将这些东西称为 hack,因为这种方式的代理具有较差的运行时时间排序质量。如果您的管理器包(隐藏和创建代理的那个)启动晚于使用该服务的包,那么您就会遇到麻烦,因为使用包暂时暴露给非代理服务。

    虽然有一些方法可以解决开始排序这个问题,但它们基本上都很糟糕,因为你现在有一个未声明的(排序)依赖项。因此,最好确保使用代理的包具有特殊的依赖关系,例如另一种服务类型或特殊的服务属性。既然依赖是显式的,你就不用再担心排序了,时间依赖现在变成了一个普通的服务依赖问题,DS和OSGi中的其他服务管理器很好地处理了。

    使用属性/其他类型进行代理

      +----------+              +----------+    proxied=true
      | register |              | using    |---|>---+ 
      +----------+              +----------+        |
            |                                       |
            |                   +----------+        |
            +-----------<|------|  manager |--------+
                                +----------+
    

    您显然不想修改注册服务的包或使用服务的包,因为这会扼杀可重用方面的整个想法。注册/使用包的程序员应该很高兴地不知道经理的计划。那么如何在 using bundle 上设置过滤器呢?

    如果您使用声明式服务 (DS),那么您很幸运!使用 DS,您可以通过 Configuration Admin 使用“目标”对服务引用设置过滤器。配置属性。因此,管理器捆绑包看到要代理的服务,它使用特殊属性注册第二个服务(例如,'proxied=true')。然后,使用包通过 Configuration Admin DS 的目标引用属性设置了一个过滤器,例如“(proxied=*)”。

    &lt;/soapbox&gt;

    【讨论】:

    • 解决启动顺序问题的另一种方法可能是使用功能。使用该服务的包可能依赖于“服务代理”功能,而管理器包可以提供该功能。
    • @Peter 这听起来像是我需要的东西,谢谢!代理“方面”捆绑包将是我们平台/框架捆绑包集的一部分,因此可以在启动级别或类似的帮助下更早地启动它。我会看看你的配置管理员建议。分配服务过滤器的代码在哪里?它是否仅适用于 DS:target 而不适用于 Blueprint 的 filter 属性?
    • @peterkriens ,我没有得到您关于订购问题的解决方案。你能指点我一份更详细的文件/指南吗?我可以知道蓝图是否可以提供相同的解决方案?
    【解决方案2】:

    虽然没有实现为代理,但蓝图拦截器可能会做你想做的事;您可以在调用原始 bean 之前或之后拦截方法调用。我认为无论如何这就是您对代理所做的事情。 Karaf 中的 Aries 蓝图实现绝对应该支持拦截器。但是,我在 Aries 源代码本身之外找不到好的文档或示例,这使得这个答案没有我希望的那么有用!

    【讨论】:

    • 谢谢!我在蓝图规范中没有发现任何关于拦截器的内容。它们是否允许一个包向另一个包的服务添加拦截器?
    • 我相信这是对蓝图规范的白羊座实现的扩展,他们希望将其提交到蓝图规范的下一版本,但我不知道这是否发生过。有时这些东西会以不同的名称标准化。他们绝对可以跨捆绑工作;我可以看到的示例都在 blueprint-core 包中,但旨在应用于用户包。例如,有一个 QuiesceInterceptor 类。它们实现了 Interceptor 接口,但我没有立即看到它们是如何注册的。
    • 我认为 Aries 实际上将您的拦截器变成了在幕后为您服务的代理类,并且正确设置代理可能很复杂,因此原则上它可以为您省去麻烦。在实践中,我不确定用户代码是否曾尝试过。
    猜你喜欢
    • 2016-03-16
    • 1970-01-01
    • 1970-01-01
    • 2013-07-03
    • 2019-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多