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!
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.
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.
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.
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) {...} }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With