Ввод списка объектов в CDI (Weld)

Скажем, у меня есть интерфейс под названием SocialNetworkService и три реализации - TwitterService, FacebookService и FriendFeedService.

Теперь я хочу, когда мой управляемый bean (или любой другой веб-компонент) получает сообщение, чтобы разделить его во всех социальных сетях. Я пробовал:

@Inject private List<SocialNetworkService> socialNetworkServices;

Но это не сработало (ошибка развертывания). (Также попытался использовать @Any классификатор - тот же результат)

Итак, есть ли способ внедрить список всех (или некоторых) реализаций интерфейса?

Я знаю правило, что данная точка инъекции не должна иметь более одного возможного bean. Наверное, я могу добиться этого, создав производителя, который создает список, и используя Instance<SocialNetworkService>, но это кажется слишком большим для этой задачи.

Ответ 1

Объединяя мои попытки с ответом на форуме Weld:

@Inject @Any
private Instance<SocialNetworkService> services;

Instance реализует Iterable, поэтому тогда можно просто использовать цикл for-each. Необходим квалификатор @Any.


Другой способ сделать это - использовать систему событий:

  • создать MessageEvent (содержащий всю информацию о сообщении)
  • вместо того, чтобы вводить список социальных сетей, просто вставьте событие:

    @Inject private Event<MessageEvent> msgEvent;
    

    и запустите его: msgEvent.fire(new MessageEvent(message));

  • наблюдать за событием во всех сервисах (независимо от их интерфейса, что может быть плюсом):

    public void consumeMessageEvent(@Observes MessageEvent msgEvent) {..}
    

Ответ 2

Я просмотрел спецификацию JSR-299, и, похоже, вы не можете делать то, что хотите сделать легко, и у меня нет достаточного опыта с Weld для предоставления кода для этого особого случая.

Однако на основе главы 12.3 "Bean Discovery" вы могли бы объявить реализации как @Alternative (чтобы избежать жалоб Weld о нескольких реализациях) и прослушивать события ProcessBean для сбора, когда видны реализации SocialNetworkService.