3

在我当前的应用程序中,我在几个地方遇到了这种模式:我在一个包中有两个服务接口,它们执行不同但相关的工作。

interface Service1 { ... }

interface Service2 { ... }

并希望让单例组件实现两者,但发现每个组件都需要对另一个组件的引用:

public class Service1Impl implements Service1 { 

    private Service2 service2;
    ...

}

public class Service2Impl implements Service2 { 

    private Service1 service1;
    ...

}

三个 OSGi 组件模型(DS、Blueprint 和 iPOJO)中的哪一个允许这样做: 1) 何时Service1ImplService2Impl在同一个包中;2)当它们在不同的包中时?

4

2 回答 2

6

声明式服务规范,版本 1.1:

112.3.5 循环引用

一组组件描述可以创建循环依赖。例如,如果组件 A 引用了组件 B 提供的服务,而组件 B 引用了组件 A 提供的服务,则如果不访问另一个组件的部分激活的组件实例,则无法满足一个组件的组件配置。SCR 必须确保组件实例永远不会被另一个组件实例访问或作为服务访问,直到它被完全激活,也就是说,如果它有一个,它已经从它的 activate 方法返回。

循环引用必须在 SCR 尝试满足组件配置时检测到,并且 SCR 必须无法满足循环中涉及的引用,并使用日志服务记录错误消息(如果存在)。但是,如果循环中的引用之一具有可选的基数,则 SCR 必须打破循环。可以满足具有可选基数的引用并将其绑定到零目标服务。因此,循环被打破,其他参考可能会得到满足。

蓝图规范明确允许这样做,前提是依赖循环的至少一个成员将其他成员作为属性而不是参数(121.2.6 循环依赖):

当请求循环的成员提供组件实例时,蓝图容器必须通过在循环的成员中找到一个破坏成员来破坏循环。破坏成员必须对导致循环的依赖项使用属性注入。蓝图容器可以选择循环中任何合适的成员来破坏成员,如果找不到这样的成员,则初始化失败或 getComponentInstance 方法必须抛出组件定义异常。

当要求提供对象时,中断成员必须返回部分初始化的组件实例。部分初始化的对象已完成所有可能的初始化,但尚未使用 initMethod(如果指定)调用,也未注入任何导致循环的属性。部分初始化的组件实例的最终确定必须延迟到中断成员已被注入循环的所有引用成员中。终结意味着注入任何剩余的未设置属性并调用 initMethod(如果指定)。

部分初始化的组件实例的结果是它们可以在设置所有属性之前使用,应用程序必须意识到这一点。

所有部分初始化的组件实例必须在蓝图容器进入运行时阶段之前完成,并且在调用 getComponentInstance 方法返回组件实例之前。必须检测通过递归调用 getComponentInstance 方法导致动态循环的用户代码并导致失败,这些循环不能被打破。

应记录所有检测到的循环。

对于 iPOJO

支持你的具体情况。我不能在不知道进一步描述的情况下谈论其他情况。

(在邮件列表中收到答复)。

于 2012-05-14T06:12:58.070 回答
3

严格来说,你说的是不可能的,因为循环依赖。

Service1 只能在 Service2 处于活动状态时才能运行,反之亦然,因此框架启动您的服务没有顺序。

据我所知,如果您将其中一个服务引用设为可选,则可以使其工作,因此它可以在注入服务之前提供其服务,因此另一个 serviceimpl 可以返回其服务。

您可以在所有三个框架中执行此操作。iPojo 有可选的引用,DS 有一个服务需求的基数设置(使用 0..1 作为可选引用而不是 1..1)。蓝图我不是很了解,但我确信可以做到。

问候, 弗兰克

于 2012-05-13T02:48:08.537 回答