You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

何时会有多个不同的ServiceReference指向同一个ServiceRegistration?

关于OSGi中多个ServiceReference指向同一ServiceRegistration的疑问与解答

OSGi规范中org.osgi.framework.ServiceReference的文档明确说明:

框架中注册的每个服务都有一个唯一的ServiceRegistration对象,并且可能有多个不同的ServiceReference对象指向它。

但观察Eclipse OSGi的具体实现org.eclipse.osgi.internal.serviceregistry.ServiceReferenceImpl,代码如下:

public class ServiceReferenceImpl<S> implements ServiceReference<S> {
    /** Registered Service object. */
    private final ServiceRegistrationImpl<S> registration;

    /**
     * Construct a reference.
     *
     */
    ServiceReferenceImpl(ServiceRegistrationImpl<S> registration) {
        this.registration = registration;
        /* We must not dereference registration in the constructor
         * since it is "leaked" to us in the ServiceRegistrationImpl
         * constructor.
         */
    }

    ...
}

该类的构造函数为默认访问权限,且仅在org.eclipse.osgi.internal.serviceregistry.ServiceRegistrationImpl<S>的构造函数中被调用:

public class ServiceRegistrationImpl<S> implements ServiceRegistration<S>, Comparable<ServiceRegistrationImpl<?>> {

    /** Reference to this registration. */
    /* @GuardedBy("registrationLock") */
    private ServiceReferenceImpl<S> reference;

    /**
     * Construct a ServiceRegistration and register the service
     * in the framework's service registry.
     *
     */
    ServiceRegistrationImpl(ServiceRegistry registry, BundleContextImpl context, String[] clazzes, S service) {
        this.registry = registry;
        this.context = context;
        this.bundle = context.getBundleImpl();
        this.clazzes = clazzes; /* must be set before calling createProperties. */
        this.service = service; /* must be set before calling createProperties. */
        this.serviceid = registry.getNextServiceId(); /* must be set before calling createProperties. */
        this.contextsUsing = new ArrayList<>(10);

        synchronized (registrationLock) {
            this.state = REGISTERED;
            /* We leak this from the constructor here, but it is ok
             * because the ServiceReferenceImpl constructor only
             * stores the value in a final field without
             * otherwise using it.
             */
            this.reference = new ServiceReferenceImpl<>(this);
        }
    }
    ...
}

另外,org.osgi.framework.ServiceRegistration接口仅提供getReference()方法,没有类似getReferences()的方法。

这就产生了疑问:什么时候会出现多个不同的ServiceReference指向同一个ServiceRegistration?

可能的场景

  • 不同BundleContext的服务查询:当不同Bundle通过各自的BundleContext查询同一服务时,框架可能返回不同的ServiceReference实例。这些实例虽指向同一注册对象,但可能关联了调用者Bundle的权限、服务可见性过滤等上下文信息。
  • 服务事件分发:框架分发服务注册、修改、注销事件时,可能为每个事件接收者创建新的ServiceReference实例,确保每个事件处理上下文的独立性。
  • 框架内部缓存与复制:部分OSGi实现会维护服务引用缓存,当缓存失效或更新时,可能创建新的ServiceReference实例关联同一注册对象,避免原实例被意外修改引发问题。
  • 权限控制需求:针对不同调用者,框架可能生成带权限标识的ServiceReference子类实例,这些实例底层指向同一注册对象,但会在方法调用时做权限校验,这类场景下也会存在多引用实例。

规范与实现的关系

OSGi规范仅要求ServiceReference的equals方法能正确判断是否指向同一ServiceRegistration,并不强制引用实例的唯一性。Eclipse的实现目前采用一个注册对象对应一个引用实例的设计,但这只是该实现的选择,其他OSGi框架(如Apache Felix)可能采用多实例实现,只要符合规范要求即可。

内容的提问来源于stack exchange,提问作者Bourbon_7

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 05:54:53