Emissary aims to take advantage of the simplicity of using the annotations for handlers (e.g. @RequestHandler/@EventHandler) without the drawbacks of reflection (slow).
What differentiates Emissary from other messaging/dispatch libraries? It takes advantage of java.lang.invoke.LambdaMetafactory to avoid the cost of invoking methods reflectively. This results in performance close to directly invoking the request handler and event handler methods.
~ 1000% more throughput compared to other similar libraries (Spring's ApplicationEventPublisher, Pipelinr, EventBus) ~ 90% faster compared to other similar libraries (Spring's ApplicationEventPublisher, Pipelinr, EventBus)
Benchmarks found on the GitHub repository: https://github.com/joel-jeremy/emissary?tab=readme-ov-file#p...
I always enjoy how low-tech this website is. Not necessarily great UX, but it's quaint.
See: https://github.com/joel-jeremy/emissary/blob/main/emissary-c...
Here are the default invocation strategies built-in right now: https://github.com/joel-jeremy/emissary/tree/main/emissary-c...
The setup is more or less similar, you register a bunch of event handlers when initializing the library. The main difference is that, in addition to events, Emissary also supports "request" messages. Requests enforce the invariant that only one handler should handle it - if there are multiple handlers registered for a given request, Emissary will throw an error. That, and some extension points which is only needed for more advance use cases.
The InstanceProvider allows users to let the dependency injection (DI) framework of their choice instantiate the request/event handler classes (see https://github.com/joel-jeremy/emissary?tab=readme-ov-file#e...). This is in contrast to the way EventBus does it where subscribers need to be instantiated at startup time. By leveraging the DI framework, additional services can be injected to the handler's constructor.