Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to make a Spring ApplicationListener listen for 2 or more types of events?

I've got 2 different types of events that I want my class to be able to listen for and process accordingly (and differently).

I tried: public class ListenerClass implements ApplicationListener<Foo>, ApplicationListener<Bar>

This gives me an error that you can't implement the same interface twice with different arguments.

Short of implementing a listener for ApplicationEvent (or some other common interface that Foo and Bar would implement) and using instanceof to determine what path to take, do I have any other options?

Thanks!

like image 500
Luke Avatar asked Jan 12 '12 13:01

Luke


People also ask

How do I listen events in spring boot?

Annotation for Spring Boot event listeners A method that listens for spring boot events is created using @EventListener . The ApplicationEventPublisher class is used to broadcast a spring boot event. When an event is published with the ApplicationEventPublisher class, the @EventListener annotated methods are called.

What is ApplicationListener in spring?

As of Spring 3.0, an ApplicationListener can generically declare the event type that it is interested in. When registered with a Spring ApplicationContext , events will be filtered accordingly, with the listener getting invoked for matching event objects only.

Are spring events asynchronous?

Annotation-Driven Event Listener By default, the listener is invoked synchronously. However, we can easily make it asynchronous by adding an @Async annotation. We just need to remember to enable Async support in the application.


1 Answers

See Spring 4.2 update at the end of this answer!

Spring < 4.2

Not really.

You can use a common super class for the argument (for example ApplicationEvent) or a common interface that Foo and Bar implements then you must fitler it by your self.

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

The other approach would be using two Application Listeners

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

Important: all 3 instances must be spring beans!


Of course you can implement such functionality by your own. You have at least two different choices, make it based on the spring event dispatcher framework or do it completely separated. For the second choice defently have a look a the CDI-Event Mechanim, and may search for some spring ports.

I have implemented the first choice by my self some years (I guess in 2007/2008) ago. I have head a event dispatcher that listend to all events. It was configured though an XML file. This xml files contains "references"! to methods in beans for every event that should been dispatched - this methods would been invoked by reflection. So it was possible to have strong typed event handler methods (that was the aim of that approach) but also to have several handler methods in one class. Nowadays I would skip the xml file and would use Annotations and a Bean-Post-Processor


Spring 4.2 update

Spring 4.2 will have an improved event listener configuration (bases on annotations) that makes it possible to have two different event listener Methods in one bean.

@Component public class ListenerClass {    @EventListener   public void handleFooEvent(Foo fooEvent) {...}    @EventListener   public void handleBarEvent(Bar barEvent) {...}  } 
like image 148
Ralph Avatar answered Sep 20 '22 15:09

Ralph