java - 使用声明式服务根据属性动态选择 OSGi 引用

标签 java dynamic osgi declarative-services

我是 OSGi 的新手,很快就被它的复杂性弄得不知所措。我相信这应该相当简单,但我还没有找到一个完整的工作示例来说明我正在努力实现的目标。

我有一个包含服务集合的 Java 类 Foo。这些服务需要根据特定于 Foo 的特定实例的值进行过滤。 Foo 可以有多个实例,但每个实例都应该有自己的一组过滤服务。

为了说明,请考虑以下示例(受 Apache Felix tutorials 启发):

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
}

看完several StackExchange posts还有一些other articles ,这似乎可以使用 ConfigurationAdmin 来完成。但是,尚不清楚应该在何处以及如何使用 ConfigurationAdmin,尤其是在声明式服务方面。我还阅读并重读了 Configuration Admin Service Specification ,但我正在努力应用这些概念。

谁能填补我理解上的空白?

提前致谢!


编辑

Christian's answer帮助我以不同的方式思考声明式服务。当我回顾我的研究时,我遇到了 Alan Hohn's blog posts on DZone再次。不幸的是,他似乎从未完成 promise 涵盖使用 DS 进行服务查找的系列文章。然而,他的example source code包含以下内容:

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 的 Elixir ,所以我很好奇是否/如何重构它以使用 DS。

最佳答案

您在 main 中的代码没有意义。

如果您使用 new 关键字创建(声明性服务)DS 组件的实例,则不会执行整个 DS 逻辑。实际上,在 OSGi 中,您根本不使用 main 方法……也许是为了启动框架而不是为了您自己的逻辑。

您可以通过创建一个使用它的 shell 命令或创建一个使用它的 http 白板服务来访问您的拼写检查器。

要在 SpellChecker 中设置服务引用过滤器,您可以使用如下配置:

pid:拼写检查器的完全限定名称


dictionaryServices.target=(language=en)

这会将 SpellChecker 设置为仅使用英语词典。

更多关于DS的小技巧可以引用 https://liquid-reality.de/2016/09/26/hints-ds.html

关于java - 使用声明式服务根据属性动态选择 OSGi 引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55653320/

相关文章:

java - Spring mvc 将数据发送到 Controller

java - 发送图片到Flash客户端。使用什么技术?

c# - 如何将动态用作泛型?

java - 确定java中的操作系统架构和位数

java - Java 8 模块与 OSGi 有何不同?

java - JDBC DatabaseMetaData 说我的 mysql 服务器不支持 namedParameters 并因此抛出空指针异常

java - 如何在 google map v2 for android 中显示标记旁边的文本

c - 我如何制作扫描用户输入(文本)并将其保存在动态字符串上的 C 程序

mysql - karaf + pax-jdbc 连接池已达到限制

java - OSGi 平台版本之间的兼容性建议