Как я понимаю, вы хотите иметь отношение 1: N между двумя компонентами.
С DS у вас есть пара альтернатив:
шаблон доски
Можно реализовать шаблон доски, где компонент 1 отслеживает регистрации служб OSGi DictionaryService.Компонент N регистрирует службы, и каждая регистрация служб перехватывается и используется зарегистрированным компонентом 1 .
Возможно, проблема в том, что вы не хотите активировать компонент 1 в производстве до тех пор, пока все ожидаемые компоненты N не зарегистрируют свои услуги и не отследят по 1 .
Используйте ссылку на множество элементов со сложнымВыражение фильтра
В конфигурации используется ссылка с несколькими значениями мощности и выражение фильтра, например: (| (language = en) (language = es))
Проблема та жекак с шаблоном доски.
Многие люди начинают писать «проверку работоспособности», где также определяется отношение 1: N, и уведомляет программиста, если запущены не все службы (или запрещает приложение быть доступным для пользователя),Проблема с подходом проверки работоспособности заключается в том, что у программиста должна быть та же логическая избыточность в системе.
Вместо DS используйте ECM (другую модель компонентов для OSGi)
Несмотря на то, что эталонный DS-шаблон и шаблон доски обеспечивают очень удобную гибкость во время разработки, он часто не подходит для производства, когда все службы должны быть внедрены до того, как приложение станет доступно пользователям.
ECM поддерживает отношение 1: N следующим образом:
- В компоненте 1 вы можете определить массив фильтров
- Компонент 1 будет удовлетворено только при наличии службы OSGi для всех указанных фильтров.
Поскольку область действия и цель компонента ECM очень похожи на область действия и цель компонента DS, люди, знающие DS, нуждаются в этом.только пару часов, чтобы выучить ECM.Поскольку ECM также зависит от служб OSGi, DS и ECM могут легко жить рядом друг с другом в одной системе и использовать службы OSGi, предоставляемые другой.
На основе вашего примера:
// All annotations from the ecm package
@Component
public class SpellChecker {
@ServiceRef
private DictionaryService[] dictionaryServices;
// I think the language should be a parameter of your service function
// rather than a member variable of your component class
public boolean check(String word, String language) {
if (word == null || word.isEmpty()) {
return true;
}
if (dictionaryServices == null || dictionaryService.length = 0) {
return false;
}
List<DictionaryService> ds = Arrays.asList(dictionaryServices);
return ds.stream().anyMatch(dictionary -> dictionary.check(word));
}
// You need a setter in case of ECM and you can annotate the setter as well.
// If you annotate the field instead, you need to specify the setter as an
// attribute of the annotation
@ServiceRef()
public void setDictionaryServices(DictionaryService[] dictionaryServices) {
this.dictionaryServices = dictionaryServices;
}
}
Компонент выше может использоваться со следующим массивом строк в конфигурации:
dictionaryServices.target = [
"(language=en)",
"(language=de)",
"(language="es")"
]
Компонент будет активирован, когда будут доступны все три ссылки, и вы получите массив служб словаря с тремяэлементы в нем (с тем же порядком в массиве, что и в конфигурации).