创建 osgi 实用程序包有多有用

how useful is to create an osgi utility bundle

我正在尝试使用 OSGi 框架开发一个简单的应用程序。我的问题涉及框架中可用的 "utility bundle" :让我用一个非常详细的例子来解释。目前我正在尝试构建我的捆绑包将发送的事件。

据我了解,我需要做的是像下面这样的事情(event admin felix):

public void reportGenerated(Report report, BundleContext context)
    {
        ServiceReference ref = context.getServiceReference(EventAdmin.class.getName());
        if (ref != null)
        {
            EventAdmin eventAdmin = (EventAdmin) context.getService(ref);

            Dictionary properties = new Hashtable();
            properties.put("title", report.getTitle());
            properties.put("path" , report.getAbsolutePath());
            properties.put("time", System.currentTimeMillis());

            Event reportGeneratedEvent = new Event("com/acme/reportgenerator/GENERATED", properties);

            eventAdmin.sendEvent(reportGeneratedEvent);
        }
    }

现在,由于 OSGi 应用程序可能有很多包,我想为每个包创建一个事件的子class(例如,我有一个名为 "BundleExample" 的包?在它里面导出classes 会有一个 "BundleExampleEvent")。我 知道这不会添加任何信息,因为您可以通过查看 "topic" 知道您收到了哪个事件,但请暂时耐心等待

现在,Event 构造函数需要一个主题和一个 Map<String, Object>。但是,对于 "simplify" 事件构造函数,我只想将主题和参数列表放入地图中。例如,这里可能是 BundleExampleEvent class:

public class BundleExampleEvent extends Event{

    private int importantVariable;

    public BundleExampleEvent(String topic, int importantVariable) {
        super(topic, Utils.toMap("importantVariable", importantVariable));
        //here toMap is static
    }

    public int getImportantVariable() {
        return this.importantVariable;
    }   
}

好的,请注意 Utils.toMap:这是一个允许您将 String, Object 序列转换为 Map 的函数。好的,现在 Utils 是实用程序 class 的示例(愚蠢、无用但仍然是实用程序 class)。 本着 OSGi 的精神,我想把这个实用程序 class 也打包成一个包:我的想法是在框架启动时启动这个 Utils 包,然后每当我需要一个包时它的实用程序我想通过 @Reference 注释获取参考。

这在任何 bundle 接口实现中都可以发挥很大的作用,像这样:

@Component
public class BundleExampleImpl implements BundleExample {
   @Reference
   private Utils utils;

   @Override
   public String sayHello() {
      return this.utils.fetchHello();
      //another useless utility function, but hopefully it conveys what i'm trying to do
   }
}

但是其他 classes(即在其工作期间由 BundleExampleImpl 调用)呢?例如 BundleExampleEvent 呢?我需要从 sayHello 方法中调用它,并且我还想在 class 中使用此实用程序来计算地图!在前面的示例中,我使用了静态函数,但我想使用 Utils OSGi 给我的参考。

当然我可以在 BundleExampleEvent 的构造函数中添加一个参数以满足 link 但我宁愿不这样做,因为它是非常愚蠢的是,某些东西将取决于 "utility class";我的问题是:

  1. 如果我想要 "utility bundle",这是唯一可用的方法吗?
  2. 或者我可以做一些奇怪的事情,比如在我的 BundleExampleEvent 中添加 Utils 的引用;即像这样的东西:

    public class BundleExampleEvent extends Event{
        @Reference
        private Utils utils;
        private int importantVariable;
    
        public BundleExampleEvent(String topic, int importantVariable) {
            super(topic, Utils.toMap("importantVariable", importantVariable));
            //here toMap is static
        }
    
        public int getImportantVariable() {
            return this.importantVariable;
        }   
    }
    
  3. 或者拥有一个 "utility bundle" 的整个想法纯粹是垃圾?

感谢您的回复。希望我能用最清楚的方式表达我的问题

在您的情况下,Utils 实用程序将是一个 OSGi 服务。然后你想在一个不是像 BundleExampleEvent 这样的服务的对象中使用这个服务。

您可以做的是创建一个服务来创建 BundleExampleEvent 实例并为其提供 OSGi 服务。有点像工厂即服务。问题在于 OSGi 中的服务是动态的。如果 BundleExampleEvent 实例所需的服务消失,则必须丢弃该对象。所以这只适用于短暂的对象。

在 eventadmin 示例中,一个不同的解决方案是不使用特殊事件 class 而是创建一个具有发送此类事件的方法的服务。然后所有的魔法都会在这个方法中发生,结果将是一个没有进一步逻辑的事件。您还可以使用 DS 将 EventAdmin 注入该服务。 这在 OSGI 中工作得很好,但有贫血域模型的缺点 (http://www.martinfowler.com/bliki/AnemicDomainModel.html)。

我不确定更喜欢哪种变体。

我不认为 Utils 是一项服务有任何意义。只有当事物可以有多种实现时,它们才应该是一种服务。在您的情况下,Util 功能的使用者只需要一个实现...实现 合同。

我什至认为 utils 代码不应该放在一个包中。只需将它变成一个静态链接到需要它的包的库。