org.springframework.context.event.AbstractApplicationEventMulticaster.ListenerRetriever#getApplicationListeners method performs an unnecessary sort:
It creates a list which is a combination of this.applicationListeners and this.applicationListenerBeans and sorts that list. However, the sorting is unnecessary if either one of the two collections is empty. Furthermore, due to the fact that the sorting utilizes the reflection lookups, this sort can become an expensive unnecessary overhead in some use cases.
In my case, I load large amounts of data (> 1K of objects) via Spring Data Mongo which fires off events for every object loaded in the system.
So the sort operation ends up taking about 38% of the overall cost of the processing, more than any other component in my use case.
AbstractApplicationEventMulticaster maintains a pre-sorted list for singleton listeners now, sourced from applicationListeners as well as applicationListenerBeans entries which happen to point to a singleton bean (which we can also reliably cache and sort upfront). This effectively avoids the sort operation for repeated listener invocations as long as all listeners are singleton beans... which is hopefully good enough for the common scenarios out there. As a side benefit, it also avoids repeated getBean retrieval for singleton listener beans.