简体   繁体   中英

Inject several of the Same CDI bean into a class?

Currently, I have everything working with one injection of my CDI bean, but I need about 6 to 10 separate instances(?) depending on my inputs. (Ideally, I would like to be able to inject a dynamic number of the same CDI beans depending on how many I need.)

Unfortunately, I need to have the beans injected since the class depends on another CDI bean. (See the 2.CDI bean class below)

  1. Clients class
@ApplicationScoped
public class Clients {
   Publisher pub;
   Subscriber sub;
   @Inject
   ListenerBean listener;

   public void init(){
      pub = new Publisher();
      sub = new Subscriber(listener);
   }
}
  1. CDI bean class
@Dependent
public class ListenerBean{
   @Inject
   private eventHandler h;

   public void onMessage(Msg msg){
      h.doesSomething();
   }
}

The functionality I'm looking for, but not sure what's available out there. I haven't found anyone looking to accomplish the same thing.

for(Subscriber s: listOfSubscribers){
   @Inject
   ListenerBean l;
   s = new Subscriber(l);
}

// The only thing I can do right now is
@Inject
ListenerBean listener1;
@Inject
ListenerBean listener2;
@Inject
ListenerBean listener3;
@Inject
ListenerBean listener4;

If you need to inject several different instances of a @Dependent scoped bean, you could do it via programmatic lookup - in other words via Instance<T> .

Every bean resolution for a @Dependent bean via Instance will result in a new bean instance created. Following code illustrates that:

@Inject Instance<ListenerBean> instance;

public void createMultipleBeanInstances() {
  // bean1 and bean2 are two different instances because the bean is @Dependent
  // you can OFC do this in a cycle and generate as many as you like
  ListenerBean bean1 = instance.get(); 
  ListenerBean bean2 = instance.get();
}

Just note that dependent beans you create via programmatic lookup have their lifecycle bound to the Instance object meaning they will exist so long as does the Instance . Given that you @Inject Instance into the bean, it will be destroyed along with the bean it was injected into.

Explanation following my comment. I might be misunderstanding your question though.

First of all, your code looks basically like the implementation of a multicaster: you inject several objects which all implement a common interface to call the same method.

I think, that in trying to inject the various receiver objects, you basically have an XY-problem: does the emitter really need to know the receivers, or is it enough, that the event reaches the targets?

If I am right with the assumption, that your emitter does not really need to know the subscribers, you can simply use the Event standard mechanism:

First, define a message (which can carry additional information, but this is not specifically necessary, you just need a class):

public class MyMessage {
     // if needed, add some fields
}

Then, in your emitter, inject the corresponding event type, and use it to fire the message:

@Inject
private Event<MyMessage> myEvent;  // note: type is message, not the bean

...

myEvent.fire(new MyMessage()); // to broadcast the message to everyone who is interested

In your subscribers, just @Observe the message:

public void theMethodWeWantCalled(@Observes MyMessage messageObject) {
    // do things here
}

That's it: no need to couple emitter and subscriber.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM