java 在 CDI(焊接)中注入对象列表

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4009388/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 04:21:09  来源:igfitidea点击:

Inject list of objects in CDI (Weld)

javacdijboss-weld

提问by Bozho

Let's say I have an interface called SocialNetworkService, and three implementations - TwitterService, FacebookServiceand FriendFeedService.

假设我有一个名为 的接口SocialNetworkService和三个实现 - TwitterServiceFacebookServiceFriendFeedService

Now I want, whenever my managed bean (or whatever web component) receives a message, to share it in all social networks. I tried:

现在我想,每当我的托管 bean(或任何 Web 组件)收到一条消息时,就在所有社交网络中共享它。我试过:

@Inject private List<SocialNetworkService> socialNetworkServices;

But it didn't work (deployment error). (Also tried to the @Anyqualifier - same result)

但它不起作用(部署错误)。(也尝试过@Any预选赛 - 结果相同)

So, is there a way to inject a list of all (or some) implementations of an interface?

那么,有没有办法注入一个接口的所有(或一些)实现的列表?

I know the rule that a given injection point should not have more than one possible bean. I guess I can achieve that by making a producer that produces the list, and using Instance<SocialNetworkService>, but that seems like too much for this task.

我知道给定注入点不应有多个可能的 bean 的规则。我想我可以通过制作一个生成列表的生产者并使用 来实现这一点Instance<SocialNetworkService>,但这对于这项任务来说似乎太多了。

回答by Bozho

Combining my attempts with an answer from the Weld forum:

将我的尝试与 Weld 论坛的答案相结合:

@Inject @Any
private Instance<SocialNetworkService> services;

Instanceimplements Iterable, so it is then possible to simply use the for-each loop. The @Anyqualifier is needed.

Instance实现Iterable,因此可以简单地使用 for-each 循环。在@Any需要预选赛。



Another way to do this is by using the event system:

另一种方法是使用事件系统:

  • create a MessageEvent(containing all the information about the message)
  • instead of injecting a list of social networks, simply inject the event:

    @Inject private Event<MessageEvent> msgEvent;
    

    and fire it: msgEvent.fire(new MessageEvent(message));

  • observe the event in all services (regardless of their interface, which might be a plus):

    public void consumeMessageEvent(@Observes MessageEvent msgEvent) {..}
    
  • 创建一个MessageEvent(包含有关消息的所有信息)
  • 无需注入社交网络列表,只需注入事件:

    @Inject private Event<MessageEvent> msgEvent;
    

    并开火: msgEvent.fire(new MessageEvent(message));

  • 观察所有服务中的事件(不管它们的界面如何,这可能是一个加分项):

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

回答by Thorbj?rn Ravn Andersen

I had a look at the JSR-299 specification and it doesn't seem that you can do what you want to do easily and I do not have experience enough with Weld to provide code for this special case.

我查看了 JSR-299 规范,似乎您无法轻松完成自己想做的事情,而且我对 Weld 的经验不足,无法为这种特殊情况提供代码。

However, based on chapter 12.3 "Bean Discovery" you might be able to declare the implementations as @Alternative's (to avoid Weld complain about multiple implementations) and listen to ProcessBean events to collect when implementations of SocialNetworkService are seen.

但是,根据第 12.3 章“Bean 发现”,您可以将实现声明为 @Alternative(以避免 Weld 抱怨多个实现)并在看到 SocialNetworkService 的实现时收听 ProcessBean 事件以进行收集。