如何在运行时控制 OSGi 中的依赖注入
How to control dependency injection in OSGi at runtime
我试图了解如何在 OSGi 中控制依赖项注入(特别是在 Adobe 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。
我试图了解如何在 OSGi 中控制依赖项注入(特别是在 Adobe 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。