Получить точный объект из введенного экземпляра CDI


У меня есть некоторые DAO, такие как UserDAO, ProductDAO и т. д. без аннотаций cdi или квалификаторов (тогда они @Default). Эти классы реализуют абстрактное Дао:

public interface DAO {
    void update();
    void delete();
    void getById(long id);
}

Таким образом, я получаю все доступные реализации DAO:

public class ClassToInjectIn {
    @Inject
    private Instance<DAO> allDAOs;
}

Теперь allDAOs содержит следующее:

[UserDAO, {@Default(), @Any()}]
[ProductDAO, {@Default(), @Any()}]

Например, мне нужно получить UserDAO из этого экземпляра, но я не могу. Я хочу сделать это так:

UserDAO user = allDAOs.get();

Но это вызывает исключение:

Исключение в потоке " main" класса javax.предприятие.впрыскивать.AmbiguousResolutionException: слишком много бобов совпадают, потому что все они имеют одинаковый приоритет.

Таким образом, проблемасостоит в том, что я не могу использовать много квалификаторов, потому что у меня есть много сущностей, и они могут быть добавлены позже. Мне нужен один универсальный метод, который может найти и извлечь объект с запрошенным типом, как это было показано в примере выше. И он не должен использовать имя класса или любые строковые имена, чтобы не указывать нужный тип или класс. Например, public DAO getNeededDAO(String neededClassName). Оно имеет динамическое определение требуемого типа / класса. Можно ли это сделать?

Обновить

Мне нужно именно это:

UserDAO user = chooseAndGetRequiredDAO();

Поэтому chooseAndGetRequiredDAO() должен понимать, что требуется тип UserDAO. Он должен искать существующие DAOs и выбирать UserDAO, если найдет. Может быть, он должен использовать reflecton или любую другую фабрику DAO, я не уверен.

3 2

3 ответа:

Ваше поле allDAOs позволяет выполнятьпрограммный поиск для всех бобов, имеющих тип DAO в их наборе типов. Но чтобы сделать поиск, вы должны дать запрос на поиск. В данном конкретном случае это комбинация типа и квалификаторов.

UserDAO user = allDAOs.select(UserDao.class).get();

Либо вы:

  • использовать @Named
  • ввести фактический интерфейс, например UserDAO, OrderDAO, ... (правильный путь)
  • введите DAOFactory с помощью метода T build(Class<T>), который вы вызываете во время выполнения, как это factory.build(User.class).getById(id) (я не предлагаю это)

Возможно, вы могли бы специализировать DAOs, если это возможно с помощью универсального параметра:

public interface DAO<T> {
   ...
}

После этого вы можете различать различные варианты с помощью универсального параметра. Хотя это работает только для CDI beans, а не для EJBs (я думаю)

@Inject
private DAO<User> userDao;

Если вы действительно хотите все DAOs, вы должны повторить allDAOs. В вашем примере:

for(DAO dao: allDAOs) {
   ...do something with dao...
}