Возможно ли динамически управлять @Named именем инъекции из файла свойств для HK2

#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, и он вернет выбранную вами реализацию.

Примечание реальный код, вероятно, хотел бы быть более сложным в отношении того, что произойдет, если не будет реализации данного имени для данной службы.