我正在尝试评估我们的商店在没有整个NetBeans平台的情况下使用NetBeans Lookup API是否合适。
到目前为止,我用以下代码创建了一个项目:
for (SomeInterface si : Lookup.getDefault().lookupAll(SomeInterface.class)) {
si.doSomething();
}
我还创建了几个其他项目,每个项目都有一个实现SomeInterface的AnImplementation类,以及附带的文件META-INF/services/path.to.SomeInterface,其中包含一行引用该类(例如"other.path.to.AnImplemention")。
当我将这些实现项目添加到NetBeans IDE中主项目的库(依赖项)中时,它运行良好,并且我可以从两个实现中看到doSomething()的连续结果。
我的问题是,如何在不参考主项目中的子项目的情况下实现这一点;在构建时,子项目的jar不会包含在主项目的生成jar中,并且可以随意添加或删除它们,从而改变上面代码的结果。
如果我没有记错的话,这就是Lookup API文档中宣传的行为。提前谢谢。
编辑:目前,我的结论是,如果没有NetBeans平台(或OSGi?),就不可能在启动时检测到哪些服务提供商。您需要在类路径中引用它们的jar,从而在启动之前识别它们。请随意证明我错了。
您必须在调用应用程序中引用子项目,因为这会将其放在类路径上-如果jar/库不在类路径中,那么Lookup和ServiceLoader等API将无法找到它。
如果您使用OSGI或NetBeans平台,这些系统允许您在运行时更改类路径。
Geertjans的博客有一个关于这一点的条目(使用NetBeans平台之外的Lookup API),在他的博客中,他还引用了John O’Connors的博客,该博客对比了ServiceLoader和Lookup API
编辑
我刚刚看到Jon Skeets对类似问题的回答。您可以使用-Djava.ext.dirs=lib
属性将文件夹(在本例中为"libs")设置为它必须查找类路径的jar的位置。
根据我的理解,您不必将所有模块与主项目捆绑在一起就可以工作。您所需要的只是确保在启动应用程序时模块位于类路径上,因为全局Lookup
在后台使用ServiceLoader机制。根据你的问题,我建议考虑
- 直接使用ServiceLoader更适合您的问题或
- 像Guice这样的DI框架值得一试,或者
- 如果OSGI也为你提供了有用的东西,并使用它
不要误解我的意思,我绝对喜欢NetBeans和NetBeans平台,但在我看来,由于上面列出的可能性,单独使用Lookup
的用途有限。