java - 使用声明式服务根据属性动态选择 OSGi 引用
问题描述
我是 OSGi 的新手,很快就被它的复杂性弄得不知所措。我相信这应该相当简单,但我无法找到一个完整的工作示例来说明我正在努力实现的目标。
我有一个Foo
包含服务集合的 Java 类。这些服务需要根据特定于Foo
. 可以有多个实例Foo
,但每个实例都应该有自己的一组过滤服务。
为了说明,请考虑以下示例(受Apache Felix 教程的启发):
public interface DictionaryService {
public boolean check(String word);
}
@Component(property = "language=en")
public class EnglishDictionaryService implements DictionaryService {
private static final String[] WORDS = {"hi", "hello" /*...*/};
@Override
public boolean check(String word) {
if (word == null || word.isEmpty()) {
return true;
}
// super inefficient but you get the gist
return Arrays.stream(WORDS).anyMatch(entry -> word.equalsIgnoreCase(entry));
}
}
@Component(property = "language=en")
public class TexanDictionaryService implements DictionaryService {
private static final String[] WORDS = {"howdy" /*...*/};
//...
}
@Component(property = "language=en")
public class AustralianDictionaryService implements DictionaryService {
private static final String[] WORDS = {"g'day" /*...*/};
//...
}
@Component(property = "language=es")
public class SpanishDictionaryService implements DictionaryService {
private static final String[] WORDS = {"hola" /*...*/};
//...
}
@Component
public class SpellChecker {
@Reference
private volatile List<DictionaryService> dictionaryServices;
public SpellChecker(String language) {
// TODO: how to ensure my dictionaryServices match the given language code?
// dictionaryServices.target = "(language=" + language + ")"
}
public boolean check(String word) {
if (word == null || word.isEmpty()) {
return true;
}
List<DictionaryService> ds = dictionaryServices;
if (ds == null || ds.isEmpty()) {
return false;
}
return ds.stream().anyMatch(dictionary -> dictionary.check(word));
}
}
public static void main(String[] args) {
SpellChecker englishChecker = new SpellChecker("en");
SpellChecker spanishChecker = new SpellChecker("es");
// do stuff
}
在阅读了几篇 StackExchange 帖子和其他一些 文章后,似乎可以使用ConfigurationAdmin
. 但是,尚不清楚ConfigurationAdmin
应该在何处以及如何使用,尤其是在声明式服务方面。我还阅读并重新阅读了Configuration Admin Service Specification,但我在努力应用这些概念。
有人可以填补我理解中的空白吗?
提前致谢!
编辑
Christian 的回答帮助我以不同的方式思考声明式服务。当我回顾我的研究时,我再次在 DZone 上看到了 Alan Hohn 的博客文章。不幸的是,他似乎从未完成他承诺使用 DS 进行服务查找的系列。但是,他的示例源代码包含以下内容:
public String greet(String language) {
BundleContext context = FrameworkUtil.getBundle(this.getClass()).getBundleContext();
String filter = "(language=" + language + ")";
// Get ServiceReference(s) from OSGi framework, filtered for the specified value
ServiceReference[] refs = null;
try {
refs = context.getServiceReferences(Greeter.class.getName(), filter);
if (null != refs) {
Greeter greeter = (Greeter)context.getService(refs[0]);
return greeter.greet();
}
} catch (InvalidSyntaxException e) {
LOGGER.error("Invalid query syntax", e);
}
LOGGER.warn("No plugins found, making the default greeting");
return "Hello from the greeter manager!";
}
这看起来是一个可行的解决方案,但它似乎没有使用 DS。这种方法有什么特别的考虑吗?我在 SO 和其他地方看到很多帖子声称 DS 是万灵药BundleContext#getServiceReferences
,所以我很好奇是否/如何将其重构为使用 DS。
解决方案
您在 main 中的代码没有意义。
如果您使用关键字创建(声明式服务)DS 组件的实例,new
则不会执行整个 DS 逻辑。实际上,在 OSGi 中,您根本不使用main
方法……也许是为了启动框架,但不是为了您自己的逻辑。
您可以通过创建使用它的 shell 命令或创建使用它的 http 白板服务来访问您的拼写检查器。
为了设置服务引用的过滤器,SpellChecker
您可以使用如下配置:
pid:拼写检查器的完全限定名
dictionaryServices.target=(language=en)
这会将 设置SpellChecker
为仅使用英文词典。
有关 DS 的更多提示,您可以参考 https://liquid-reality.de/2016/09/26/hints-ds.html
推荐阅读
- oracle - 什么是“Oracle 的 SQL:2011 方言”?
- websocket - 在 websocket 中丢失会话
- javascript - 使用Javascript点击棘手的选择HTML元素
- python - 如何在 python 中获取 Wifi IP
- c - CYGWIN 控制台中的奇怪错误“检测到 cygheap 基础不匹配”
- javascript - 如何在错误对话框显示中显示 php 错误消息?
- java - Android - 视频活动
- python - 使用 python 并行运行 n 个 MATLAB 实例
- javascript - AJAX:如何在 vanilla JS 中通过 POST 发送简单参数
- python - 循环的条件下拉菜单未按预期方式工作