Hands-On Reactive Programming in Spring 5
上QQ阅读APP看书,第一时间看更新

Publish-Subscribe pattern with @EventListener

It would be awkward to develop software with the need to re-implement the same software patterns again and again. Luckily, we have Spring Framework, plenty of adorable libraries, and other superb frameworks (Spring is not the only one). As we all know, Spring Framework provides most of the building blocks we could ever need for software development. Of course, for a long time, the framework had its own implementation of the Observer Pattern, and this was widely used for tracking the application's life cycle events. Starting with Spring Framework 4.2, this implementation and concomitant API was extended to be used for the handling of not only application events but also business logic events. In turn, for the event distribution purposes, Spring now provides an @EventListener annotation for event handling and the ApplicationEventPublisher class for event publishing.

Here we need to clarify that the @EventListener and the ApplicationEventPublisher implement the Publish-Subscribe pattern, which may be seen as a variation of the Observer pattern.

A good description of the Publish-Subscribe pattern can be found at: http://www.enterpriseintegrationpatterns.com/patterns/messaging/PublishSubscribeChannel.html.

In contrast to the Observer pattern, in the Publish-Subscribe pattern publishers and subscribers don't need to know each other, as is depicted in the following diagram: 

Diagram 2.3 The Observer pattern (on the left) versus the Publish-Subscribe pattern (on the right)

A Publish-Subscribe pattern provides an additional level of indirection between the publishers and subscribers. The subscribers are aware of the event channels that broadcast notifications, but usually do not care about publishers' identities. Also, each event channel may have a few publishers at the same time. The preceding diagram should help to spot the difference between Observer and Publish-Subscribe patterns. The Event Channel (also known as a message broker or event bus) may additionally filter incoming messages and distribute them between subscribers. The filtering and routing may happen based on the message content, message topic, or sometimes even both. Consequently, subscribers in a topic-based system will receive all messages published to the topics of interest. 

The Spring Framework's @EventListener annotation makes it possible to apply both topic-based and content-based routing. Message types could play the role of topics; the condition attribute enables content-based routing event handling based on the Spring Expression Language (SpEL).

As an alternative to the Spring-based implementation of the Publish-Subscribe pattern, there is a popular open source Java library called MBassador . It has the single purpose of providing a light-weight, high-performance event bus that implements the Publish-Subscribe pattern. Authors claim that MBassador preserves resources while delivering high performance. This is because it has almost no dependencies and does not restrict  the design of our application. For more details, please refer to the project page on GitHub ( https://github.com/bennidi/mbassador ). Also, the Guava library provides EventBus, which implements the Publish-Subscribe pattern. The following article describes the API and includes code samples for Guava EventBus: (https://github.com/google/guava/wiki/EventBusExplained).