Select 某些 CDI 事件观察者

Select certain CDI event observer

我有几个 classes 观察一些 CDI 事件。是否可以声明在不同情况下应使用哪个 class?

例如我有 class 产生事件:

class Producer
   {
        @Inject
        private Event<SomeEvent> event;
        public void fire()
        {
             event.fire(new SomeEvent());
        }
   }

我有两个消费者 classes:

class ConsumerA
{
       public void onEvent(@Observes SomeEvent event);
}
class ConsumerB
{
       public void onEvent(@Observes SomeEvent event);
}

如何在一种情况下使用 ConsumerA 个实例,在另一种情况下如何使用 ConsumerB 个实例?

我需要这样的东西:

class UseCaseA
{
    @Inject
    Producer producer;
    @Inject
    ConsumerA consumerA;
    public void doWork()
    {
         producer.fire(); //consumerA.onEvent() will be called
    }
}
class UseCaseB
{
    @Inject
    Producer producer;
    @Inject
    ConsumerB consumerB;
    public void doWork()
    {
         producer.fire(); //consumerB.onEvent() will be called
    }
}

这里的技巧是对事件和观察者都进行限定。

See the jee6 tutorial here 特别是 @Credit@Debit 限定符的使用。

要动态执行此操作而不是注入不同的事件来触发,您可以在单个事件上使用 select(java.lang.annotation.Annotation... qualifiers) 方法。

确定您的观察员资格,然后致电。

event.select(.... Some annotation literal. .).fire();

您可以在 superclass 中包含 fire 代码,然后让每个 subclass 提供注释文字。

注释文字是javax.enterprise.util.AnnotationLiteral。 您将需要为要使用的每个限定符创建注释文字,但这些可以实例化并作为对象传递。

顺便说一句,你不需要注入你的观察者。这违背了这一点。您应该能够为每个事件添加任意数量的观察者,而不必重新访问事件的来源。您的容器应在启动时实例化它们。

您也可以 select 基于事件 class 的子class 事件,如果效果更好的话。

编辑: 只是想我会对此添加关于使用事件的哲学的想法。

  1. 触发事件的组件可以指定附加到事件的有效负载和限定符的具体类型,但不会也不应实际选择将处理事件的观察者。
  2. 您可以为任何一个事件添加多个观察者。可能有:一个发送电子邮件;一个写审计日志;一个发送短信;一个写JMS消息;由于一次 event.fire(...) 调用,还有更多的都同时触发。
  3. 观察员IMO应该像上面描述的那样有一个单一的目的。

  4. 观察者不应依赖任何执行顺序(除了事务性与非事务性……见下文),因为它不能得到保证。如果您需要保证顺序,那么观察者应该触发一个不同的事件,该事件的观察者可以按顺序进行后续处理。

  5. 像上面描述的那些具有单一目的的小型观察者很容易超级class因为大多数代码通常是相同的,例如。对于除邮件格式之外的所有电子邮件。
  6. 如果您有 2 个更新要执行并且不能使用 XA 来保证单个原子事务。您可以决定最重要的,并为同步执行的那个(在触发事务中)设置一个观察者,为另一个在触发事务成功后执行的观察者(使用 during=AFTER_SUCCESS)设置一个不同的观察者,这样您可以保证 :A 和 B 都会发生;或 A 会发生但 B 不会发生。这样你甚至可以进行一些定期检查以从 A
  7. 的结果传播 B
  8. @Observes 注释的 during 参数可用于在与触发事件的组件关联并同步执行(非事务性)的核心处理与不得采取的处理之间提供分离放置在某些情况下与触发事件的事务相关的地方,并且在这些情况下执行"queued"(事务性),例如,如果事务失败则记录错误;或发送邮件,如果交易成功。