如何在运行时控制 OSGi 中的依赖注入

How to control dependency injection in OSGi at runtime

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

在 servlet 中:

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

和我的实现 class:

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

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

到目前为止,一切顺利 -- 除了要更改我需要重新编译和重新部署的值。我需要在运行时或通过绑定到环境或 "runmode" 的配置文件来控制它。我不知道该怎么做。

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

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

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

有什么方法可以在不修改、重新编译、重新部署源代码的情况下控制注入哪个class?

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

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

@Reference(policyOption=ReferencePolicyOption.GREEDY)

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

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

target.signingProvider=(myproperty=myvalue)

我又收集了一些提示here