【问题标题】:Does OSGi enforce service ranking order when injecting a listOSGi 在注入列表时是否强制执行服务排名顺序
【发布时间】:2025-12-21 02:15:12
【问题描述】:

当在服务中使用@Reference 来注入对多个服务(ReferenceCardinality.MULTIPLE)实现的引用时,OSGi 对注入服务的排序方式做出什么保证?他们总是按service.ranking 订购吗?

目前我执行以下操作:

@Reference(
    service = SomeInterface.class,
    cardinality = ReferenceCardinality.MULTIPLE,
    policy = ReferencePolicy.DYNAMIC,
    policyOption = ReferencePolicyOption.GREEDY,
    fieldOption = FieldOption.UPDATE
)
private final List<SomeInterface> refs = new CopyOnWriteArrayList<>();

(注解是 OSGi R7 的注解)

在测试时,我总是看到列表 refs 上的元素按其 service.ranking 的降序排列,但我不知道这是设计使然还是偶然,以及 OSGi 是否保证。我在规范或任何博客文章中都没有找到明确的答案。

此外,当为 policypolicyOptionfieldOption 使用不同的值时,这是否成立?

【问题讨论】:

    标签: osgi aem


    【解决方案1】:

    由于您提供自己的列表(并且不让声明式服务 (DS) 提供列表),DS 只能在您的列表对象上调用 addremove。见https://docs.osgi.org/specification/osgi.cmpn/7.0.0/service.component.html#d0e37871

    由于 DS 仅调用您的列表对象,因此您的列表实现必须负责任何所需的排序。

    如果您让 DS 提供该列表,则该列表将始终按以下顺序排序:“根据服务排名和服务 ID 使用与 ServiceReference.compareTo 相同的顺序进行排序”。见https://docs.osgi.org/specification/osgi.cmpn/7.0.0/service.component.html#d0e37828

    【讨论】:

    • 我认为这将涉及将字段设为非final 并将fieldOption 更改为REPLACE,对吗?
    • 奇怪的是,当我这样做时,顺序会发生变化,因此排名最低的服务在列表中排在第一位。我觉得这有点奇怪。该规范明确指出,较高的排名意味着该服务是首选的,所以我预计排序顺序是降序,而不是升序......
    • DS 规范声明集合按自然顺序排序,通常是升序。所以集合中的最后一项是排序中最高的。
    • @RaphaelSchweikert 你有没有挖掘更多的推理(例如在 OSGi 邮件列表上),因为它也让我感到惊讶。如果“最佳”服务是排名最高的服务(如 BundleContext.getServiceReference() 所建议的),为什么该列表从最不受欢迎的服务开始?我知道它在 DS 规范中,但为什么呢?
    • @BJHargrave 当我尝试使用 AemContext(它使用 org.apache.sling.testing.mock)测试该字段时,顺序颠倒(排名最高的服务首先出现)。你知道为什么吗?