Ввод списка объектов в 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.