如何在 OSGi 中将 ManagedServiceFactory 正确实现为声明式服务?

2024-03-26

我有需要在每个配置基础上创建的服务,每个服务都依赖于外部资源,因此应该管理它自己的生命周期(即(取消)注册服务)。因此,将这些实现为 DS 并让 SCR 生成多个实例是行不通的。

人们可以实现一个注册 ManagedServiceFactory 的包来完美地完成此任务(请参阅我之前的帖子 https://stackoverflow.com/questions/11832204/how-do-you-implement-a-managedservicefactory-in-osgi)。但结果是,如果工厂依赖于其他几个服务,您需要开始跟踪这些服务并编写大量粘合代码以使所有内容运行。相反,我想将工厂实现为(单例)声明性服务,SCR 为其注册一个ManagedServiceFactory在服务注册中心。

这是我的尝试:

import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.cm.ManagedServiceFactory;
import org.osgi.service.component.ComponentContext;

@SuppressWarnings({ "rawtypes", "unchecked" })
public class Factory implements ManagedServiceFactory {

private BundleContext bundleCtxt;
private Map<String, ServiceRegistration> services;

public void activate(ComponentContext context) throws Exception {
    System.out.println("actiavting...");
    this.bundleCtxt = context.getBundleContext();
    services = new HashMap<String, ServiceRegistration>();
}

public void deactivate(ComponentContext context) {
    for(ServiceRegistration reg : services.values()) {
        System.out.println("deregister " + reg);
        reg.unregister();
    }
    services.clear();
}

@Override
public String getName() {
    System.out.println("returning factory name");
    return "my.project.servicefactory";
}


@Override
public void updated(String pid, Dictionary properties)
        throws ConfigurationException {
    System.out.println("retrieved update for pid " + pid);
    ServiceRegistration reg = services.get(pid);
    if (reg == null) {
        services.put(pid, bundleCtxt.registerService(ServiceInterface.class,
                new Service(), properties));
    } else {
        // i should to some update here
    }
}

@Override
public void deleted(String pid) {
    ServiceRegistration reg = services.get(pid);
    if (reg != null) {
        reg.unregister();
        services.remove(pid);
    }
}
}

以及服务描述:

<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" configuration-policy="ignore" name="my.project.servicefactory">
   <implementation class="my.project.factory.Factory"/>
   <service>
      <provide interface="org.osgi.service.cm.ManagedServiceFactory"/>
   </service>
   <property name="service.pid" type="String" value="my.project.servicefactory"/>
</scr:component>

我已经发现服务描述中的“factory”属性是错误的路径,因为这样组件永远不会注册为ManagedServiceFactory在服务注册表中,它变成了ComponentFactory.

作为一种 hack,我只是添加了一个组件属性,即

<property name="service.pid" type="String" value="my.project.servicefactory"/>

并添加了configuration-policy="ignore"。这有效:名为的配置my.project.servicefactory-foobar.cfg交给我的服务,该服务将它们注册在服务注册表中,一切都很好。

但有两点我不喜欢:

  1. 手动设置属性service.pid对我来说感觉就像是一个肮脏的黑客
  2. setting configuration-policy="ignore"阻止我配置ManagedServiceFactory它本身。如果我逃避这个属性或将其设置为需要,我会得到一个ManagedServiceFactory对于名为my.project.servicefactory.cfg然后为每个配置提供两个以模式命名的服务my.project.servicefactory-foobar.cfg: one ManagedServiceFactorySCR 产生并且一个ServiceInterface那是我的第一个ManagedServiceFactory当收到有关此新配置的通知时进行注册。 (至少这不会呈指数增长,因为 SCR 会覆盖service.pid工厂配置的属性)

那么我应该如何正确设置呢?

PS:对于那些想知道我对其文件名的配置的引用的人:我使用 Felix Fileinstall 进行配置,因此foo.cfg被放入 PID 的 ConfigAdminfoo, and foo-bar.cfg放在那里是为了factory-pid foo.


只需使用您的无头 DS 实例的属性,然后自行注册服务:

@Component(immedate=true, provide={}, serviceFactory=true, configurationPolicy=require)
public class Mine {
    BundleContext context;
    volatile ServiceRegistration r;

    @Activate
    void activate(BundleContext context, Map<String,Object> map) {
         this.context = context;
         track(map);
    }

    @Deactivate
    void deactivate() {
        if ( r != null)
              r.unregisterService();
    }

    void track(Map<String,Object> map) {
       ... // do your remote stuff
       r = context.registerService(...);
       ...
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 OSGi 中将 ManagedServiceFactory 正确实现为声明式服务? 的相关文章

随机推荐

  • 如何在 iPhone 的自定义 UIView 上启用 UIDragInteraction

    我一直在尝试使用 Apple 的新 API 来启用自定义 UIView 上的拖动交互 我在使用 iPad 进行测试时成功地使其工作 但是当我在 iPhone 7 ios 11 beta 3 中运行相同的应用程序时 我无法拖动我的自定义 UI
  • SQL Server:将 bool 转换为整数

    为什么查询 SELECT CAST column LIKE string AS INT 100 return 关键字 AS 附近的语法不正确 因为 bool 不是 T SQL 中的类型 它不存在 布尔表达式不是位类型 他们不have类型 仅
  • 如何在 Polymer 1.0 中过滤铁列表?

    The dom repeat元素提供了一个filter属性 有没有类似的过滤方法iron list 例如 给定一个人员列表 我想过滤出生在特定城市的人 As iron list不幸的是不提供filter属性 没有声明性模式使这成为可能 您可
  • ActiveRecord:如何找到所有孩子都符合条件的父母?

    假设我有一个Parent模型有很多Child 然后Child也属于OtherParent 我怎样才能找到全部Parent其中所有的Child属于任何OtherParent 在纯 SQL 中我可以做 Parent find by sql lt
  • PySpark 可以使用 numpy 数组吗?

    我尝试在 pyspark 会话中执行以下命令 gt gt gt a 1 2 3 4 5 6 7 8 9 10 gt gt gt da sc parallelize a gt gt gt da reduce lambda a b a b 效果
  • 我的 onChange 不适用于反应

    我已经关注了这个文档 https facebook github io react docs forms html why select value并使用 React 创建了一个选择标签 我已经编辑了这个问题 如果我在选择中使用 class
  • 无法更新公司防火墙后面的 conda 软件包。更新了 .condarc 文件,代理设置仍然要求代理用户名和密码

    我位于公司防火墙后面 我正在尝试通过运行以下命令来更新 conda 软件包 conda update all 这是要求我提供代理用户名和密码 https proxy username https proxy username Passwor
  • 公开存储库的子集,同时保留历史记录

    我有一些受版本控制的代码 使用 Mercurial 并且想分享其中的一些代码 同时隐藏我无法发布到公共领域的其他部分 至少在现阶段 理想情况下 我希望保持公共代码的修订历史记录完整 更重要的是 能够在公共存储库和包含公共和私有代码的存储库之
  • 计算列表内列表之间的最小长度

    a 1 0 1 2 1 1 1 3111111 31 1 4 51 1 1 1 1 1 6 7 8 print min a 0 a 1 a 2 以下代码返回 1 0 1 2 1 1 1 3111111 不确定默认键是什么以及根据什么逻辑返回
  • 如何在购物篮中显示正确的税费(结账前)?

    我有一个简单的问题 我为不同国家设置了多种税率 但是 在购物篮页面上 当尚未访问结帐页面时 它会显示来自基准国家 地区的税费 就我而言 我在 AT 有一家商店 我已经为 AT 和 CH 设置了税费 如果用户使用瑞士 IP 进行访问 我会将国
  • 合并多个data.table

    我知道一个人可以合并 加入 两个data table与merge函数或 data table功能 然而 如果我说 10 data table并想要使用do call将它们全部合并在一起 是否有一个函数可以做到这一点 目前我求助于do cal
  • 覆盖 Object.toString 错误

    为什么这会在 Flash Builder 中产生错误 package public class Foo override public function toString String return Foo 制表符补全表明这可用于覆盖 错误
  • Silverlight 4 组合框下拉显示不一致

    我有一个 Silverlight 4 应用程序 在窗体底部附近有一个组合框 下拉列表中可以包含大约 30 到 100 个项目 当我第一次打开 ComboBox 时 没有 SelectedItem Dropdown 向上打开 大约有 23 个
  • GMail 线程、IMAP 和 Ruby

    我正在使用 Ruby IMAP 库来获取 GMail 对话 GMail 线程对话的方式是通过 Message ID 和 In Reply To 消息标头 例如 In Reply To lt email protected cdn cgi l
  • 在网页上包含不引人注目的信息的最佳方式

    所以我写了一些脚本 在我的页面上设置了谷歌地图 这些脚本包含在我的页面 并使用 jQuery 使用从页面上的地址列表生成的标记来构建地图 但是 我有每个地址的一些精确坐标数据 JavaScript 需要这些数据才能正确放置标记 这不是我希望
  • 为什么最终变量必须在构造函数完成之前初始化?

    为什么最终变量必须在构造函数完成之前初始化 public class Ex final int q 当我编译这段代码时 我收到这样的错误 错误 变量 q 可能尚未初始化 The official原因是它是由Java 语言规范 8 3 1 2
  • UIAlertView/UIAlertController iOS 7 和 iOS 8 兼容性

    我正在使用 Swift 编写一个应用程序 我需要显示一个警报 该应用程序必须兼容 iOS 7 和 iOS 8 自从UIAlertView已替换为UIAlertController 我如何检查是否UIAlertController不检查系统版
  • 如何更改 WinApi C++ 中控件的字体?

    如何更改 win32 API 中编辑控件的字体 我希望能够在编辑控件上编辑字体的样式和颜色 首先 您应该澄清您正在谈论的是标准编辑控件与 Rich Edit 控件 两者完全不同 您可以通过发送更改字体WM SETFONT http msdn
  • Socket.io,socket.set() 和套接字属性之间的区别?

    Socket io 建议设置每个套接字变量 如下所示 socket set foo bar function 还可以在套接字上设置和访问变量 socket foo bar 使用提供的 set 函数有好处吗 Calling socket fo
  • 如何在 OSGi 中将 ManagedServiceFactory 正确实现为声明式服务?

    我有需要在每个配置基础上创建的服务 每个服务都依赖于外部资源 因此应该管理它自己的生命周期 即 取消 注册服务 因此 将这些实现为 DS 并让 SCR 生成多个实例是行不通的 人们可以实现一个注册 ManagedServiceFactory