2012-01-12 22 views
22

Tôi có 2 loại sự kiện khác nhau mà tôi muốn lớp học của mình có thể nghe và xử lý tương ứng (và khác biệt).Có thể tạo một Spring ApplicationListener nghe 2 hoặc nhiều loại sự kiện không?

tôi đã cố gắng: public class ListenerClass implements ApplicationListener<Foo>, ApplicationListener<Bar>

này mang lại cho tôi một lỗi mà bạn không thể thực hiện cùng một giao diện hai lần với lập luận khác nhau.

Ngắn thực hiện trình lắng nghe cho ApplicationEvent (hoặc một số giao diện chung khác mà Foo và Bar sẽ triển khai) và sử dụng instanceof để xác định đường đi nào, tôi có tùy chọn nào khác không?

Cảm ơn!

Trả lời

28

Xem bản cập nhật Spring 4.2 ở cuối câu trả lời này!

Xuân < 4,2

Không thực sự.

Bạn có thể sử dụng một lớp siêu phổ biến cho đối số (ví dụ ApplicationEvent) hoặc giao diện chung mà Foo và Bar thực hiện sau đó bạn phải điều chỉnh nó bằng chính bản thân bạn.

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

Cách tiếp cận khác sẽ được sử dụng hai Listeners Application

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

Chú ý: tất cả 3 trường hợp phải đậu mùa xuân!


Tất nhiên bạn có thể tự mình thực hiện chức năng này. Bạn có ít nhất hai lựa chọn khác nhau, làm cho nó dựa trên khung điều phối sự kiện mùa xuân hoặc làm nó hoàn toàn tách biệt. Đối với sự lựa chọn thứ hai rõ ràng có một cái nhìn một CDI-Event Mechanim, và có thể tìm kiếm một số cổng mùa xuân.

Tôi đã thực hiện lựa chọn đầu tiên của mình một vài năm (tôi đoán trong 2007/2008) trước đây. Tôi đã đứng đầu một người điều phối sự kiện để lắng nghe tất cả các sự kiện. Nó được cấu hình mặc dù một tập tin XML. Tệp xml này chứa "tham chiếu"! với các phương thức trong bean cho mọi sự kiện cần được gửi đi - các phương thức này sẽ được gọi bởi sự phản chiếu. Vì vậy, nó đã có thể có phương pháp xử lý sự kiện đánh mạnh mẽ (đó là mục đích của phương pháp đó) mà còn có một số phương pháp xử lý trong một lớp. Ngày nay tôi sẽ bỏ qua các tập tin xml và sẽ sử dụng chú thích và một Bean-Post-Processor


mùa xuân 4,2 cập nhật

Spring 4.2 will have an improved event listener cấu hình (căn cứ vào chú thích) mà làm cho nó có thể có hai sự kiện khác nhau phương pháp nghe trong một bean.

@Component 
public class ListenerClass { 

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

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

} 
+0

Tôi đang làm điều gì đó tương tự như đề xuất đầu tiên của bạn ngay bây giờ, nhưng đó là một loại phổ biến giữa Foo và Bar (thay vì đối tượng). Lựa chọn thứ hai không phải là một sự thỏa hiệp xấu tôi đoán. Nó vẫn không lý tưởng. Tôi đã thực sự hy vọng rằng tôi đã nhìn thấy một cái gì đó. Có vẻ như đây phải là một vấn đề phổ biến. – Luke

+0

Ngoài ra, 'publishEvent' lấy một' ApplicationEvent' để bạn không thể có một sự kiện Object được gửi đi, nó sẽ phải là một cái gì đó thực hiện 'ApplicationEvent' ít nhất. Có thể muốn thay đổi điều đó để làm ví dụ đầu tiên của bạn rõ ràng hơn. – Luke

+0

'ApplicationEvent' và' Object' bạn đúng, dù sao cũng giống như nguyên tắc. - Tôi đã chỉnh sửa nó – Ralph

3

Xuân < 4,2

tao nhã hơn một chút so với instanceof hoặc static class là mô hình khách truy cập.Tôi nghĩ rằng mô hình khách truy cập cung cấp một lựa chọn rất hữu ích cho sự thiếu sót của mùa xuân cũ hơn.

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); 
    } 
} 
Các vấn đề liên quan