简体   繁体   English

OSGi 中仅运行时依赖项的最佳实践

[英]Best practices for runtime-only dependencies in OSGi

In line with the Open-Closed Principle , I typically design my Java packages and libraries in such a way that there is a generic "interface" or "API" package/library and one or more implementations (quite similar to many common APIs like JDBC or JAXP/SAX).根据开闭原则,我通常设计我的 Java 包和库的方式是有一个通用的“接口”或“API”包/库和一个或多个实现(非常类似于许多常见的 API,如 JDBC或 JAXP/SAX)。 To locate an implementation (or sometimes multiple implementations) in the base API library without violating OCP, I commonly use Java's ServiceLoader mechanism, or occasionally classpath scanning via third-party libraries like ClassGraph or Reflections .为了在不违反 OCP 的情况下在基本 API 库中找到一个实现(或有时是多个实现),我通常使用 Java 的ServiceLoader机制,或者偶尔通过ClassGraphReflections等第三方库进行类路径扫描。 From a Maven perspective, the implementations are brought in as runtime dependencies (as they're only needed at execution time, but not at compile time).从 Maven 的角度来看,实现是作为runtime依赖项引入的(因为它们仅在执行时需要,但在编译时不需要)。 Pretty standard stuff.很标准的东西。

So, now, I want to make some of these packages available as OSGi bundles (with API and implementation in separate bundles), but since in OSGi each bundle has its own class loader, neither classpath scanning nor the ServiceLoader API will work for this purpose.所以,现在,我想将这些包中的一些作为 OSGi 包提供(使用 API 并在单独的包中实现),但由于在 OSGi 中,每个包都有自己的 class 加载器,类路径扫描和ServiceLoader ZDB97423781014CA8ACE4FZA 都不能用于此目的. At first glance, OSGi's "fragment" mechanism seems to be the closest equivalent to the plain-Java setup described above.乍一看,OSGi 的“片段”机制似乎与上述纯 Java 设置最接近。 In that scenario, the API bundle would be the "fragment host", and concrete implementations would attach as fragments to that host bundle.在这种情况下,API 包将是“片段主机”,具体实现将作为片段附加到该主机包。 As the fragment host and all its attached fragments use the same class loader, the standard plain-Java mechanisms like ServiceLoader or ClassGraph would conceivably still work.由于片段主机及其所有附加片段使用相同的 class 加载器,因此可以想象像ServiceLoader或 ClassGraph 这样的标准纯 Java 机制仍然可以工作。 This would also have the advantage that there would be no need to detect whether a library/bundle is running in an OSGi context or not, and no OSGi framework dependencies are needed.这还有一个优点,那就是不需要检测库/包是否在 OSGi 上下文中运行,并且不需要 OSGi 框架依赖项。

So, in a nutshell, my question is: are fragments the correct way to implement runtime-only dependencies in OSGi or is there a better (or more standard) way?所以,简而言之,我的问题是:片段是在 OSGi 中实现仅运行时依赖项的正确方法,还是有更好(或更标准)的方法? Preferably, I'm looking for a solution that works in an OSGi container but does not require a dependency on OSGi itself.最好,我正在寻找一种在 OSGi 容器中工作但不需要依赖于 OSGi 本身的解决方案。

No Fragments are almost always wrong outside the translations.没有片段在翻译之外几乎总是错误的。 The OSGi model is to use services . OSGi model 是使用服务

The way to go then is to use DS. go 的方法是使用 DS。 Using bnd (in maven, gradle, ant, sbt, or Bndtools) you can create components .使用 bnd(在 maven、gradle、ant、sbt 中,您可以创建组件。) A component is a Plain Old Java Object (POJO) that is annotated with injection and activation instructions.组件是一个普通的旧 Java Object (POJO),带有注入和激活说明。 You could make those components to take all its dependencies in the constructor.您可以使这些组件在构造函数中获取其所有依赖项。

The bnd code uses the annotations to generate an XML file that is used in runtime to create, activate, inject, and register those components. bnd 代码使用注释生成 XML 文件,该文件在运行时用于创建、激活、注入和注册这些组件。 This will then work out of the box in an OSGi Framework.这将在 OSGi 框架中开箱即用。 The annotations are build time so they do not create dependencies in your runtime.注释是构建时间,因此它们不会在您的运行时创建依赖项。

In your non-OSGi environment, you'd be responsible to call that constructor yourself.在您的非 OSGi 环境中,您将负责自己调用该构造函数。 So you gather your dependencies using the Service Loader and then construct them in the right order.因此,您使用 Service Loader 收集依赖项,然后以正确的顺序构建它们。

@Component
public class MyComponent implements Foo {

      final Bar bar;

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM