在与线开闭原则,我通常设计我的Java包和库以这样的方式,有一个通用的“界面”或“API”包/库和一个或多个实现(非常相似,如JDBC许多共同的API或JAXP / SAX)。为了在不违反OCP的情况下在基本API库中定位一个实现(有时是多个实现),我通常使用Java的ServiceLoader机制,或者偶尔通过第三方库(如ClassGraph或Reflections)进行类路径扫描。从Maven的角度来看,实现是作为runtime
依赖项引入的(因为它们仅在执行时需要,而在编译时则不需要)。很标准的东西。
因此,现在,我想将其中一些软件包作为OSGi捆绑包提供(带有API和在单独的捆绑包中的实现),但是由于在OSGi中每个捆绑包都有自己的类加载器,因此类路径扫描和ServiceLoader
API都不能用于此目的。乍一看,OSGi的“碎片”机制似乎与上述纯Java设置最接近。在那种情况下,API束将是“片段主机”,而具体的实现将作为片段附加到该主机束。由于片段主机及其所有附加片段都使用相同的类加载器,因此标准的纯Java机制如ServiceLoader
或者ClassGraph仍然可以正常工作。这还将具有以下优点:不需要检测库/捆绑包是否在OSGi上下文中运行,并且不需要OSGi框架依赖项。
因此,简而言之,我的问题是:片段是在OSGi中实现仅运行时依赖项的正确方法,还是有更好(或更标准)的方法?最好是,我正在寻找一种可以在OSGi容器中运行但不需要依赖于OSGi本身的解决方案。
在翻译之外,没有片段几乎总是错误的。OSGi模型是使用服务。
接下来的方法是使用DS。使用bnd(在maven,gradle,ant,sbt或Bndtools中)可以创建components。组件是一个普通的老式Java对象(POJO),该对象带有注入和激活指令。您可以使这些组件在构造函数中采用其所有依赖性。
bnd代码使用注释生成XML文件,该XML文件在运行时用于创建,激活,注入和注册这些组件。这将在OSGi框架中立即可用。注释是构建时间,因此它们不会在运行时中创建依赖项。
在非OSGi环境中,您有责任自己调用该构造函数。因此,您可以使用Service Loader收集依赖关系,然后以正确的顺序构造它们。
@Component
public class MyComponent implements Foo {
final Bar bar;
@Activate
public MyComponent( @Reference Bar bar ) {
this.bar = bar;
}
...
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句