【问题标题】:How to control dependency injection in OSGi at runtime如何在运行时控制 OSGi 中的依赖注入
【发布时间】:2018-04-24 01:30:15
【问题描述】:

我正在尝试了解如何在 OSGi(特别是 Adob​​e Experience Manager (AEM) 中使用的 Apache Felix)中控制依赖注入。我在一个引用接口的字段上有一个带有@Reference 注释的servlet——在我的例子中,它代表一个安全的文档签名提供程序。我有一个实现接口的实现类,它会自动注入到 servlet 中。

在 servlet 中:

@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
private DocumentSigningProvider signingProvider;
...
URL redirectUrl = signingProvider.Sign(...);

和我的实现类:

@Component(metatype=true)
@Service
@Property(name = "service.ranking", intValue = 1000)
public class DocumentSigningProviderDocuSignImpl implements DocumentSigningProvider {

如果我编写第二个实现,我可以通过service.ranking 值控制注入哪一个——最高数字获胜。如果没有在任何实现上声明排名,则最老的获胜。

到目前为止,一切都很好——除了要更改我需要重新编译和重新部署的值。我需要在运行时或通过与环境或“运行模式”相关的配置文件来控制它。我不知道该怎么做。

由于@Component 声明了metatype=true@Property 注释 类在 OSGi 控制台的 GUI 中生成一个控件。我可以使用该 GUI 在运行时更改值。但是service.ranking 是在@Property 中声明的类本身,它似乎不会在GUI 中生成控件。

此外,以类命名的配置文件在运行时提供默认值,我可以为每个环境或“运行模式”设置不同的配置文件。这对我也有用;在一个环境中,我可以配置一个模拟实现,并在另一个环境中使用“真实”实现。但同样,这些配置文件似乎适用于 @Property 声明 inside 类,但不适用于 on 类。

我在这里阅读了很多关于这个主题的帖子,但没有一个涉及在 OSGi GUI 或配置文件中公开service.ranking

有什么方法可以控制注入哪个类而不需要修改、重新编译和重新部署源代码?

【问题讨论】:

    标签: java dependency-injection osgi apache-felix


    【解决方案1】:

    在声明式服务中,您可以通过为组件提供配置并设置属性来在运行时覆盖任何服务属性。 所以设置service.ranking=1 或类似的应该实际上可以工作。

    有一点需要注意。默认情况下,声明式服务绑定到第一个可用服务并保持不变。因此,如果您想确保使用排名较高的服务,即使它晚于排名较低的服务,那么您需要在消费者端使用此选项:

    @Reference(policyOption=ReferencePolicyOption.GREEDY)
    

    这样可以确保 DS 在以后有更好的服务时切换服务。

    如果您想更具体地在消费者端使用什么服务,您也可以在运行时使用过滤器。

    target.signingProvider=(myproperty=myvalue)
    

    我又收集了一些提示here

    【讨论】:

    • 这听起来很有希望,但对我不起作用。我克隆了我的 impl 类并将“2”附加到名称中。我还复制了配置文件,检查了与 impl 类匹配的名称,并将 service.ranking="1" 添加到 orig 和 service.ranking="2" 到新副本。当我运行时,我看到了副本中的日志条目,它具有更高的等级。然后我切换了配置值:我将原始的值设置为“2”,将副本的值设置为“1”。我重新构建、重新部署并再次运行了我的应用程序,但日志条目仍然来自副本,即使它现在的 svc 排名较低。确保我反弹了我的 JVM,结果相同
    • 配置看起来像:sling.apache.org/jcr/sling/1.0" xmlns:jcr="@987654323 @" xmlns:nt="jcp.org/jcr/nt/1.0" jcr:primaryType="sling:OsgiConfig" docusign.hostname="demo.docusign.net" docusign.username="xxx" docusign.password="yyy" docusign.apikey=" ABCD-12345abc-6de7-980f-a1b2-c3def4a56b7c" service.ranking="1" /> docusign.xxx 属性工作正常,但 service.ranking 似乎被忽略了,因为无论值如何,都注入了相同的类。
    • 还有一件事——我目前仍在使用 Felix SCR 注释,而不是新的标准 OSGi DS 注释。我们在项目中收到的代码都是 Felix 风格的,我继续采用这种风格。您的建议是否仅适用于 DS 注释,还是也适用于 SCR 注释?
    • 两种注释样式都在构建时转换为 xml。所以在运行时它应该适用于两者。您可以使用 Web 控制台检查是否应用了服务属性。在您的情况下,问题可能是 service.ranking 如果服务已经绑定,则不考虑在内。
    • 无论我做什么都无法让它工作。在 Web 控制台中,我已取消绑定服务、删除配置、禁用服务并在每次更改后重新部署,但我没有做任何事情使系统选择具有更高 service.ranking 值的组件。我会接受这个答案,但我很惊讶我在这方面遇到了多少麻烦——而且这不是一个广泛讨论的话题;这是 DI 的主要用例。也许我需要开始考虑使用 Maven 仅在特定的构建/运行模式中部署我想要的类。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-25
    • 2020-12-29
    • 2012-11-23
    • 1970-01-01
    • 2017-09-16
    • 2012-03-14
    • 1970-01-01
    相关资源
    最近更新 更多