【问题标题】:Select certain CDI event observer选择某个 CDI 事件观察者
【发布时间】:2015-04-05 01:24:52
【问题描述】:

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

例如,我有产生事件的类:

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

我有两个消费者类:

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
    }
}

【问题讨论】:

  • 我会避免为此使用名称 Producer,除非这具有不可避免的商业意义。 CDI 中的生产者方法和字段是对容器的 bean 创建逻辑的添加。

标签: java jakarta-ee dependency-injection cdi java-ee-6


【解决方案1】:

这里的诀窍是同时限定事件和观察者。

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

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

确认你的观察者,然后打电话。

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

您可以在一个超类中包含触发代码,然后让每个子类提供注释文字。

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

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

如果效果更好,您还可以根据事件类的子类选择事件。

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

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

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

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

【讨论】:

  • 所以我不能选择外部生产者逻辑的观察者?我在 qt Signals-Slots 模型中梦想过类似 connect() 的东西。
  • 是什么驱动了 Producer。该类可以提供 Annotation.Literal。说producer.fire (new BAnnotationLiteral());
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-11-05
  • 2021-02-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-08
相关资源
最近更新 更多