2012-01-12 75 views
22

我有兩種不同類型的活動,我希望我的班級能夠聽取和處理(以及不同的)。是否有可能使Spring ApplicationListener偵聽2種或更多類型的事件?

我想: public class ListenerClass implements ApplicationListener<Foo>, ApplicationListener<Bar>

這給了我,你不能使用不同的參數執行兩次相同的接口錯誤。

對ApplicationEvent(或Foo和Bar將實現的一些其他通用接口)實現一個偵聽器並使用instanceof來確定要採取什麼路徑,我還有其他選項嗎?

謝謝!

回答

28

請參閱本答案最後的Spring 4.2更新!

春< 4.2

不是真的。

您可以爲參數(例如ApplicationEvent)或Foo和Bar實現的通用接口使用通用超類,那麼您必須通過自己來裝配它。

public class ListenerClass implements ApplicationListener<ApplicationEvent> { 
    ... 
    if(event instanceOf Foo || event instance of Bar) { 
    } 
} 

另一種方法將使用兩個應用聽衆

public class ListenerClass { 

    void onFoo(Foo foo){} 
    void onBar(Bar bar){} 

    static class FooListener implements ApplicationListener<Foo> { 
     ListenerClass listerner; 
     .... 
     public void onApplicationEvent(Foo foo) { 
      listener.onFoo(foo); 
     } 
    } 
    static class BarListener implements ApplicationListener<Bar> { 
     ListenerClass listerner; 
     .... 
     public void onApplicationEvent(Bar bar) { 
      listener.onBar(bar); 
     } 
    } 
} 

重要提示:所有3個實例必須是春天豆!


當然,您可以自己實現這樣的功能。你至少有兩個不同的選擇,使它基於spring事件分派器框架或完全分離。對於第二種選擇,我們可以看看CDI-Event Mechanim,並且可以搜索一些彈簧端口。

我已經實施了我自己的第一個選擇幾年前(我猜在2007/2008年)之前。我有一個事件調度員,負責所有事件。它是通過XML文件配置的。這個XML文件包含「引用」!對於應該分派的每個事件的bean中的方法 - 這些方法會被反射調用。所以有可能有強類型的事件處理方法(這是該方法的目標),但也有一個類中有多個處理方法。現在我會跳過XML文件,並會使用註解和豆後處理器


春4.2更新

Spring 4.2 will have an improved event listener配置(上標註基地),使得它可能有兩個不同的事件監聽器方法在一個bean中。

@Component 
public class ListenerClass { 

    @EventListener 
    public void handleFooEvent(Foo fooEvent) {...} 

    @EventListener 
    public void handleBarEvent(Bar barEvent) {...} 

} 
+0

我正在做類似於你現在的第一個建議,但它是Foo和Bar(而不是對象)之間的常見類型。第二種選擇不是我猜想的妥協。它仍然不理想。我真的希望我能忽略一些東西。這似乎是一個普遍的問題。 – Luke 2012-01-12 18:01:25

+0

另外,'publishEvent'接受一個'ApplicationEvent',所以你不能發送一個Object事件,它必須至少實現'ApplicationEvent'。可能想改變這一點,讓你的第一個例子更清晰。 – Luke 2012-01-12 18:50:43

+0

'ApplicationEvent' vs'Object'你是對的,無論如何它是相同的princip。 - 我改正了它 – Ralph 2012-01-12 20:52:48

3

春< 4.2

instanceofstatic class多一點優雅是訪問者模式。我認爲訪問者模式提供了一個非常有用的替代老春天的缺點。

public class ListenerClass implements ApplicationListener<FooBarBase>, FooBarVisitor { 
    @Override 
    public void onApplicationEvent(FooBarBase fooBarBase) { 
     fooBarBase.accept(this); 
    } 

    @Override 
    public void visitFoo(Foo foo) { 
     System.out.println("Handling Foo Event..."); 
    } 

    @Override 
    public void visitBar(Bar bar) { 
     System.out.println("Handling Bar Event..."); 
    } 
} 

public interface FooBarVisitor { 
    void visitFoo(Foo foo); 
    void visitBar(Bar bar); 
} 

public abstract class FooBarBase extends ApplicationEvent { 
    public FooBarBase(Object source) { 
     super(source); 
    } 

    abstract void accept(FooBarVisitor visitor); 
} 

public class Bar extends FooBarBase { 
    public Bar(Object source) { 
     super(source); 
    } 

    @Override 
    void accept(FooBarVisitor visitor) { 
     visitor.visitBar(this); 
    } 
} 

public class Foo extends FooBarBase { 
    public Foo(Object source) { 
     super(source); 
    } 

    @Override 
    void accept(FooBarVisitor visitor) { 
     visitor.visitFoo(this); 
    } 
} 
相關問題