首页 > 解决方案 > OSGi 中仅运行时依赖项的最佳实践

问题描述

根据开闭原则,我通常以这样一种方式设计我的 Java 包和库,即有一个通用的“接口”或“API”包/库和一个或多个实现(非常类似于许多常见的 API,如 JDBC或 JAXP/SAX)。为了在不违反 OCP 的情况下在基础 API 库中定位一个实现(或有时是多个实现),我通常使用 Java 的ServiceLoader机制,或者偶尔通过ClassGraphReflections等第三方库进行类路径扫描。从 Maven 的角度来看,实现是作为runtime依赖项引入的(因为它们仅在执行时需要,而不是在编译时需要)。很标准的东西。

所以,现在,我想将其中一些包作为 OSGi 包提供(API 和实现在单独的包中),但由于在 OSGi 中每个包都有自己的类加载器,因此类路径扫描和ServiceLoaderAPI 都不能用于此目的。乍一看,OSGi 的“片段”机制似乎与上述纯 Java 设置最接近。在这种情况下,API 包将是“片段主机”,具体实现将作为片段附加到该主机包。由于片段宿主及其所有附加片段使用相同的类加载器,标准的纯 Java 机制如ServiceLoader或者 ClassGraph 仍然可以想象。这还有一个优点,那就是不需要检测库/包是否在 OSGi 上下文中运行,并且不需要 OSGi 框架依赖项。

所以,简而言之,我的问题是:片段是在 OSGi 中实现仅运行时依赖项的正确方法,还是有更好(或更标准)的方法?最好,我正在寻找一种在 OSGi 容器中工作但不需要依赖于 OSGi 本身的解决方案。

标签: javaosgidependency-managementloose-couplingosgi-fragment

解决方案


没有片段在翻译之外几乎总是错误的。OSGi 模型是使用服务

那么要走的路是使用DS。使用 bnd(在 maven、gradle、ant、sbt 或 Bndtools 中)您可以创建组件。组件是带有注入和激活指令注释的普通旧 Java 对象 (POJO)。您可以使这些组件在构造函数中获取其所有依赖项。

bnd 代码使用注释生成一个 XML 文件,该文件在运行时用于创建、激活、注入和注册这些组件。这将在 OSGi 框架中开箱即用。注释是构建时间,因此它们不会在您的运行时创建依赖项。

在您的非 OSGi 环境中,您将负责自己调用该构造函数。因此,您使用 Service Loader 收集依赖项,然后以正确的顺序构建它们。

@Component
public class MyComponent implements Foo {

      final Bar bar;

      @Activate
      public MyComponent( @Reference Bar bar ) {
        this.bar = bar;
      }
      ...
}

推荐阅读