gpt4 book ai didi

java - 如何使用 OSGi 标准功能以编程方式在 SCR 中注册服务?

转载 作者:行者123 更新时间:2023-11-30 06:08:59 24 4
gpt4 key购买 nike

我花了一些时间试验和研究 OSGi enRoute 站点。 Quick Start , 和 Base教程真的很好。现在,作为学习练习,我将按照这些教程中的原则创建自己的示例。

我决定重现 StageService来自博文“Making JavaFX better with OSGi”。而不是使用 org.apache.felix.dmorg.apache.felix.dm.annotation.api我想使用 OSGi 标准 SCR 包 ( org.osgi.service.component.* ) 以及 enRoute 提供程序模板。

目前一切顺利。但我被困在一点上。在“使用 OSGi 使 JavaFX 更好”教程中,使用 org.apache.felix.dm.DependencyManager 以编程方式将服务注册到服务注册表中。像这样:

 @Override
public void start(Stage primaryStage) throws Exception {

BundleContext bc = FrameworkUtil.getBundle(this.getClass()).getBundleContext();
DependencyManager dm = new DependencyManager(bc);

dm.add(dm.createComponent()
.setInterface(StageService.class.getName(), null)
.setImplementation(new StageServiceImpl(primaryStage)));
}

我的假设是,在这个例子中 DependencyManager是 Apache Felix 特定的功能,而不是 OSGi 标准。我想让我的 enRoute 提供程序仅依赖于 OSGi 标准功能。

所以我的问题很简单:

  1. 如何仅使用 OSGi 标准功能以编程方式在服务注册表中注册服务? (我从 enRoute 教程中了解到,如果我的组件实现了导出的服务,那么当我的组件被激活时,SCR 将自动在服务注册表中注册我的组件。但是这个解决方案的问题是,当我的组件被激活时,它必须在不同的线程中启动 JavaFX 应用程序,以便在 JavaFX 应用程序终止之前不阻塞 SCR 使用的线程。因此,我的组件必须以编程方式在服务注册表中注册服务。否则它不会保证在注册时可用。)

作为引用,这是我目前拥有的:

private void registerService(Stage stage) {
DependencyManager dm = new DependencyManager(bundle().getBundleContext());
dm.add(
dm.createComponent()
.setInterface(StageService.class.getName(), null)
.setImplementation(new StageServiceImpl(primaryStage))
);
}

但是我想用这个替换它:

private void registerService(Stage stage) {
// How to register service in service registry using only OSGi standard features? (not the apache felix dependency manager)
}

更新 1

按照 BJ Hargrave 的建议,我尝试直接从 bundle context 注册服务,如下所示:

FrameworkUtil
.getBundle(getClass())
.getBundleContext()
.registerService(StageService.class, new StageServiceImpl(primaryStage), null);

执行此操作并尝试解析 enRoute 应用程序项目后,出现以下错误:

org.osgi.service.resolver.ResolutionException: Unable to resolve <> version=null: missing requirement com.github.axiopisty.osgi.javafx.launcher.application -> Unable to resolve com.github.axiopisty.osgi.javafx.launcher.application version=1.0.0.201608172037: missing requirement objectClass=com.github.axiopisty.osgi.javafx.launcher.api.StageService]

我已经将项目上传到github这样您就可以重现错误。

更新 2

提供程序模块中 bnd.bnd 文件中的构建选项卡显示以下警告:

The servicefactory:=true directive is set but no service is provided, ignoring it

这可能与无法解析应用程序模块有关吗?

最佳答案

在极少数情况下,需要使用标准 OSGi API 注册“手动服务”。尽量避免这种情况,因为如果您开始注册(并且可能依赖)您手动注册的服务,您将承担很多通常隐藏在 View 之外的责任。例如,您必须确保您注册的服务也未注册。

在极少数情况下,有必要这样做的情况之一是您必须等待条件才能注册您的服务。例如,您需要在为设备注册服务之前轮询硬件。您将需要控制 CPU,但此时您还不能注册服务。在这种情况下,您可以创建一个 immediate 组件并手动注册该服务。

要手动注册服务,您需要一个 BundleContext 对象。您可以通过 activate 方法获取该对象,只需在其参数中声明一个 Bundle Context 即可自动注入(inject):

@Activate
void activate( BundleContext context) {
this.context = context;
}

您现在可以使用 bundle 上下文注册服务:

void register(MyService service) {
Hashtable<String,Object> properties = new Hashtable<>();
properties.put("foo", "bar");
this.registration = context.registerService( MyService.class, service, properties );
}

但是,您现在有责任在停用时取消注册此服务。如果您不清理此服务,那么您的组件 可能会被停用,而您的服务仍然存在。您的服务不受管理。 (虽然当 bundle 停止时它会被清理。)

@Deactivate
void deactivate() {
if ( this.registration != null)
this.registration.unregister();
}

如果您创建的服务是回调或后台线程,那么您显然必须处理并发问题。您必须确保在停用方法完成时没有注册服务的竞争条件。

此文本也已添加到 DS Page OSGi 途中

关于java - 如何使用 OSGi 标准功能以编程方式在 SCR 中注册服务?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39004498/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com