#java #dependency-injection #aop #hk2 #qualifiers
#java #внедрение зависимостей #aop #hk2 #квалификаторы
Вопрос:
У нас есть основное Java-приложение и разные плагины для разных клиентов. Мы используем Hk2 для внедрения зависимостей.
Теперь я хотел бы узнать, возможно ли иметь способ поместить некоторые имена квалификаторов @Named в файлы свойств плагинов, чтобы я мог просто изменить значение файла свойств для внедрения разных реализаций класса для разных клиентов.
Я имею в виду @Named (ключ =»plugins.impl.xplugin»), а не @Named(«XPlugin»).
Это очень помогло бы избавиться от такого большого количества шаблонного кода для плагинов.
Комментарии:
1. Можете ли вы немного подробнее рассказать о том, что вы хотите, чтобы произошло? Мне не совсем понятно, как вы хотите, чтобы эта система работала.
2. Конечно. Допустим, у меня есть базовое приложение с двумя разными клиентами. Для сервиса в настоящее время я реализую классы ServiceImpA и ServiceImpB для внедрения специфичных для клиента реализаций некоторых функций. Но в настоящее время это просто шаблонный код. Я хотел бы иметь общий интерфейс и реализацию, управляемую файлом свойств, чтобы я мог внедрять разные реализации сервиса A для разных клиентов. Я не уверен, достаточно ли этого, или я могу попытаться нарисовать некоторую подробную диаграмму, чтобы быть более понятным.
3. Похоже, вы запрашиваете что-то, что выходит за рамки системы инъекций. Вероятно, вам придется реализовать это самостоятельно. Условное связывание не так сложно реализовать. Похоже, это в значительной степени то, что вы ищете.
4. Дело в том, что инъекция выполняется во время выполнения. Действительно кажется возможным решить, какая реализация будет внедрена, прочитав путь к классу реализации из внешнего файла свойств.
5. Вы когда-нибудь слышали о ServiceLoader ? Может быть, вы ищете что-то подобное? Когда вы говорите «чтение пути к классу реализации из внешнего файла свойств» , это первое, что приходит на ум. Многие системы «плагинов» на самом деле используют это. Смотрите также
Ответ №1:
Это возможное решение для вас с использованием IterableProvider (в котором есть «именованный» метод для выбора конкретной именованной версии во время выполнения):
@Service
public class Example {
@Inject
private IterableProvider<MyService> myService;
public MyService getSpecificService(String serviceName) {
return myService.named(serviceName).get();
}
@Contract
public interface MyService {}
@Service @Named("Foo")
public static class MyServiceFoo implements MyService {}
@Service @Named("Bar")
public static class MyServiceBar implements MyService {}
}
В приведенном выше примере вы просто передаете имя нужного вам сервиса («Foo» или «Bar») в getSpecificService, и он вернет выбранную вами реализацию.
Примечание реальный код, вероятно, хотел бы быть более сложным в отношении того, что произойдет, если не будет реализации данного имени для данной службы.