2015-04-05 98 views
0

我有幾個類可以觀察一些CDI事件。是否可以聲明哪些類應該用於不同的情況?選擇某些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 
    } 
} 
+0

我會避免使用名稱生產者爲此,除非這具有不可避免的業務含義。 CDI中的生產者方法和字段被添加到容器的bean創建邏輯中。 – redge 2015-04-05 02:23:03

回答

3

這裏的技巧是既資格的事件和觀察者。

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. 觀察員應該有像上述那樣的單一目的。

  4. 觀察者不應該依賴任何執行順序(除了事務性和非事務性......見下文),因爲它不能得到保證。如果您需要保證訂單,那麼觀察員應該發出不同的事件,並且該事件的觀察者可以按順序執行後續處理。

  5. 具有上述單一用途的小型觀察者很容易超類,因爲大部分代碼都是相同的,例如。除郵件格式外的所有電子郵件。
  6. 如果您有2個更新要執行,並且無法使用XA來保證單個原子事務。你可以決定最重要的,併爲那個同步執行(在射擊事務中)和另一個在射擊事務成功後執行的另一個觀察者(使用during=AFTER_SUCCESS)制定一個觀察者,這樣你可以保證:A和B會發生;或A會發生,但B不會。這樣,您甚至可以進行一些定期檢查,以便從A
  7. 的結果中傳播B @Observes註釋的during參數可用於在與觸發事件的組件相關聯的核心處理之間提供分離並同步執行(非事務性)和處理,除非在某些情況下與事件被觸發的事務相關,並且在這些情況下「排隊」執行(事務性),例如事務失敗時記錄錯誤;或者如果交易成功發送電子郵件。
+0

所以我不能選擇外部**生產者邏輯的觀察員**?我夢到有一些像qt Signals-Slots模型中的connect()。 – jekamax 2015-04-05 02:10:12

+0

什麼驅動生產者。該類可以提供Annotation.Literal。說'producer.fire(new BAnnotationLiteral());' – redge 2015-04-05 02:15:34