Use @EventListener annotation on multiple events in Spring

It's nominally easy to create an event listener that listens for multiple events:

@EventListener({EventA.class, EventB.class})
public doSomething() {
   ...
}

But obviously this approach does not give you access to the underlying event. Based on the javadoc for EventListener it does not appear to be possible to do what you are suggesting

If an annotated method supports a single event type, the method may declare a single parameter that reflects the event type to listen to. If an annotated method supports multiple event types, this annotation may refer to one or more supported event types using the classes attribute. See the classes() javadoc for further details.

...

If (the classes) attribute is specified with a single value, the annotated method may optionally accept a single parameter. However, if this attribute is specified with multiple values, the annotated method must not declare any parameters.

Thus there does not appear to be any mechanism to consume multiple events and take a different action based on the body of those events. I would suggest that this shouldn't be necessary though, you could always register event-specific @EventListener methods, and then just have them call a shared method to perform any common functionality.

Source: https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/event/EventListener.html


Since Spring 4.2 you can use subclass in method declaration to handle all events those extends this subclass:

@EventListener
public void handleEvent(ApplicationEvent event) {
  // listen all descendants of the ApplicationEvent
}

UPDATE 2020-10-07:
NOTE: Solution below works but contradicts with official documentation (https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/event/EventListener.html#classes--) and may stop working in next Spring releases.

Also you can narrow list of events by using annotion's attribute:

@EventListener({ContextRefreshedEvent.class, ApplicationReadyEvent.class})
public void handleEvent(Object event) {
  // listen only ContextRefreshedEvent and ApplicationReadyEvent
}