From ee688929fd5b2cf34aca83d54fbcfae2a0d05f6d Mon Sep 17 00:00:00 2001 From: kske Date: Tue, 2 Nov 2021 19:33:18 +0100 Subject: [PATCH 1/3] Add callback event handling The EventHandler class has been converted to an interface, with the reflection specific part being moved to the new ReflectiveEventHandler class. Callback event handlers implement the same interface through the CallbackEventHandler class. The event handlers are defined in the new handler package, which is not exported by the eventbus.core module. --- .../java/dev/kske/eventbus/core/Event.java | 2 +- .../java/dev/kske/eventbus/core/EventBus.java | 111 ++++++++++++++++-- .../core/handler/CallbackEventHandler.java | 73 ++++++++++++ .../eventbus/core/handler/EventHandler.java | 53 +++++++++ .../ReflectiveEventHandler.java} | 102 ++++++---------- .../eventbus/core/handler/package-info.java | 8 ++ .../dev/kske/eventbus/core/DispatchTest.java | 18 ++- 7 files changed, 280 insertions(+), 87 deletions(-) create mode 100644 event-bus-core/src/main/java/dev/kske/eventbus/core/handler/CallbackEventHandler.java create mode 100644 event-bus-core/src/main/java/dev/kske/eventbus/core/handler/EventHandler.java rename event-bus-core/src/main/java/dev/kske/eventbus/core/{EventHandler.java => handler/ReflectiveEventHandler.java} (50%) create mode 100644 event-bus-core/src/main/java/dev/kske/eventbus/core/handler/package-info.java diff --git a/event-bus-core/src/main/java/dev/kske/eventbus/core/Event.java b/event-bus-core/src/main/java/dev/kske/eventbus/core/Event.java index 6ef1dd9..f194c56 100644 --- a/event-bus-core/src/main/java/dev/kske/eventbus/core/Event.java +++ b/event-bus-core/src/main/java/dev/kske/eventbus/core/Event.java @@ -22,7 +22,7 @@ import java.lang.annotation.*; public @interface Event { /** - * Defines the event type the handler listens to. If this value is set, the handler is not + * Defines the event type the handler listens for. If this value is set, the handler is not * allowed to declare parameters. *

* This is useful when the event handler does not utilize the event instance. diff --git a/event-bus-core/src/main/java/dev/kske/eventbus/core/EventBus.java b/event-bus-core/src/main/java/dev/kske/eventbus/core/EventBus.java index b49f353..ec467f8 100644 --- a/event-bus-core/src/main/java/dev/kske/eventbus/core/EventBus.java +++ b/event-bus-core/src/main/java/dev/kske/eventbus/core/EventBus.java @@ -5,6 +5,9 @@ import java.lang.System.Logger.Level; import java.lang.reflect.InvocationTargetException; import java.util.*; import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Consumer; + +import dev.kske.eventbus.core.handler.*; /** * Event listeners can be registered at an event bus to be notified when an event is dispatched. @@ -56,6 +59,19 @@ public final class EventBus { private static final Logger logger = System.getLogger(EventBus.class.getName()); + /** + * Compares event handlers based on priority, but uses hash codes for equal priorities. + * + * @implNote As the priority comparator by itself is not consistent with equals (two handlers + * with the same priority are not necessarily equal, but would have a comparison + * result of 0), the hash code is used for the fallback comparison. This way, + * consistency with equals is restored. + * @since 1.2.0 + */ + private static final Comparator byPriority = + Comparator.comparingInt(EventHandler::getPriority).reversed() + .thenComparingInt(EventHandler::hashCode); + /** * Returns the default event bus, which is a statically initialized singleton instance. * @@ -154,18 +170,19 @@ public final class EventBus { * Searches for the event handlers bound to an event class. This includes polymorphic handlers * that are bound to a supertype of the event class. * - * @param eventClass the event class to use for the search + * @param eventType the event type to use for the search * @return a navigable set containing the applicable handlers in descending order of priority * @since 1.2.0 */ - private NavigableSet getHandlersFor(Class eventClass) { + private NavigableSet getHandlersFor(Class eventType) { // Get handlers defined for the event class - TreeSet handlers = bindings.getOrDefault(eventClass, new TreeSet<>()); + TreeSet handlers = + bindings.getOrDefault(eventType, new TreeSet<>(byPriority)); // Get polymorphic handlers for (var binding : bindings.entrySet()) - if (binding.getKey().isAssignableFrom(eventClass)) + if (binding.getKey().isAssignableFrom(eventType)) for (var handler : binding.getValue()) if (handler.isPolymorphic()) handlers.add(handler); @@ -223,11 +240,8 @@ public final class EventBus { continue; // Initialize and bind the handler - var handler = new EventHandler(listener, method, annotation, polymorphic, priority); - bindings.putIfAbsent(handler.getEventType(), new TreeSet<>()); - logger.log(Level.DEBUG, "Binding event handler {0}", handler); - bindings.get(handler.getEventType()) - .add(handler); + bindHandler( + new ReflectiveEventHandler(listener, method, annotation, polymorphic, priority)); handlerBound = true; } @@ -238,6 +252,85 @@ public final class EventBus { listener.getClass().getName()); } + /** + * Registers a callback listener, which is a consumer that is invoked when an event occurs. The + * listener is not polymorphic and has the {@link #DEFAULT_PRIORITY}. + * + * @param the event type the listener listens for + * @param eventType the event type the listener listens for + * @param callback the callback that is invoked when an event occurs + * @since 1.2.0 + * @see #registerListener(Class, Consumer, boolean, int) + */ + public void registerListener(Class eventType, Consumer callback) { + registerListener(eventType, callback, false, DEFAULT_PRIORITY); + } + + /** + * Registers a callback listener, which is a consumer that is invoked when an event occurs. The + * listener has the {@link #DEFAULT_PRIORITY}. + * + * @param the event type the listener listens for + * @param eventType the event type the listener listens for + * @param callback the callback that is invoked when an event occurs + * @param polymorphic whether the listener is also invoked for subtypes of the event type + * @since 1.2.0 + * @see #registerListener(Class, Consumer, boolean, int) + */ + public void registerListener(Class eventType, Consumer callback, + boolean polymorphic) { + registerListener(eventType, callback, polymorphic, DEFAULT_PRIORITY); + } + + /** + * Registers a callback listener, which is a consumer that is invoked when an event occurs. The + * listener is not polymorphic. + * + * @param the event type the listener listens for + * @param eventType the event type the listener listens for + * @param callback the callback that is invoked when an event occurs + * @param priority the priority to assign to the listener + * @since 1.2.0 + * @see #registerListener(Class, Consumer, boolean, int) + */ + public void registerListener(Class eventType, Consumer callback, int priority) { + registerListener(eventType, callback, false, priority); + } + + /** + * Registers a callback listener, which is a consumer that is invoked when an event occurs. + * + * @param the event type the listener listens for + * @param eventType the event type the listener listens for + * @param callback the callback that is invoked when an event occurs + * @param polymorphic whether the listener is also invoked for subtypes of the event type + * @param priority the priority to assign to the listener + * @since 1.2.0 + */ + public void registerListener(Class eventType, Consumer callback, boolean polymorphic, + int priority) { + Objects.requireNonNull(callback); + if (registeredListeners.contains(callback)) + throw new EventBusException(callback + " already registered!"); + logger.log(Level.INFO, "Registering callback event listener {0}", + callback.getClass().getName()); + + registeredListeners.add(callback); + bindHandler(new CallbackEventHandler(eventType, callback, polymorphic, priority)); + } + + /** + * Inserts a new handler into the {@link #bindings} map. + * + * @param handler the handler to bind + * @since 1.2.0 + */ + private void bindHandler(EventHandler handler) { + bindings.putIfAbsent(handler.getEventType(), new TreeSet<>(byPriority)); + logger.log(Level.DEBUG, "Binding event handler {0}", handler); + bindings.get(handler.getEventType()).add(handler); + } + /** * Removes a specific listener from this event bus. * diff --git a/event-bus-core/src/main/java/dev/kske/eventbus/core/handler/CallbackEventHandler.java b/event-bus-core/src/main/java/dev/kske/eventbus/core/handler/CallbackEventHandler.java new file mode 100644 index 0000000..0bd1541 --- /dev/null +++ b/event-bus-core/src/main/java/dev/kske/eventbus/core/handler/CallbackEventHandler.java @@ -0,0 +1,73 @@ +package dev.kske.eventbus.core.handler; + +import java.lang.reflect.InvocationTargetException; +import java.util.function.Consumer; + +/** + * An event handler wrapping a callback method. + * + * @author Kai S. K. Engelbart + * @since 1.2.0 + */ +public class CallbackEventHandler implements EventHandler { + + private final Class eventType; + private final Consumer callback; + private final boolean polymorphic; + private final int priority; + + /** + * Constructs a callback event handler. + * + * @param the event type of the handler + * @param eventType the event type of the handler + * @param callback the callback method to execute when the handler is invoked + * @param polymorphic whether the handler is polymorphic + * @param priority the priority of the handler + * @since 1.2.0 + */ + @SuppressWarnings("unchecked") + public CallbackEventHandler(Class eventType, Consumer callback, boolean polymorphic, + int priority) { + this.eventType = eventType; + this.callback = (Consumer) callback; + this.polymorphic = polymorphic; + this.priority = priority; + } + + @Override + public void execute(Object event) throws InvocationTargetException { + try { + callback.accept(event); + } catch (RuntimeException e) { + throw new InvocationTargetException(e, "Callback event handler failed!"); + } + } + + @Override + public String toString() { + return String.format( + "CallbackEventHandler[eventType=%s, polymorphic=%b, priority=%d]", + eventType, polymorphic, priority); + } + + @Override + public Consumer getListener() { + return callback; + } + + @Override + public Class getEventType() { + return eventType; + } + + @Override + public int getPriority() { + return priority; + } + + @Override + public boolean isPolymorphic() { + return polymorphic; + } +} diff --git a/event-bus-core/src/main/java/dev/kske/eventbus/core/handler/EventHandler.java b/event-bus-core/src/main/java/dev/kske/eventbus/core/handler/EventHandler.java new file mode 100644 index 0000000..60fc059 --- /dev/null +++ b/event-bus-core/src/main/java/dev/kske/eventbus/core/handler/EventHandler.java @@ -0,0 +1,53 @@ +package dev.kske.eventbus.core.handler; + +import java.lang.reflect.InvocationTargetException; + +import dev.kske.eventbus.core.*; + +/** + * Internal representation of an event handling method. + * + * @author Kai S. K. Engelbart + * @since 1.2.0 + * @see EventBus + */ +public interface EventHandler { + + /** + * Executes the event handler. + * + * @param event the event used as the method parameter + * @throws EventBusException if the event handler isn't accessible or has an invalid + * signature + * @throws InvocationTargetException if the handler throws an exception + * @throws EventBusException if the handler has the wrong signature or is inaccessible + * @since 1.2.0 + */ + void execute(Object event) throws EventBusException, InvocationTargetException; + + /** + * @return the listener containing this handler + * @since 1.2.0 + */ + Object getListener(); + + /** + * @return the event type this handler listens for + * @since 1.2.0 + */ + Class getEventType(); + + /** + * @return the priority of this handler + * @since 1.2.0 + * @see Priority + */ + int getPriority(); + + /** + * @return whether this handler is polymorphic + * @since 1.2.0 + * @see Polymorphic + */ + boolean isPolymorphic(); +} diff --git a/event-bus-core/src/main/java/dev/kske/eventbus/core/EventHandler.java b/event-bus-core/src/main/java/dev/kske/eventbus/core/handler/ReflectiveEventHandler.java similarity index 50% rename from event-bus-core/src/main/java/dev/kske/eventbus/core/EventHandler.java rename to event-bus-core/src/main/java/dev/kske/eventbus/core/handler/ReflectiveEventHandler.java index f22ddf0..22ecea5 100644 --- a/event-bus-core/src/main/java/dev/kske/eventbus/core/EventHandler.java +++ b/event-bus-core/src/main/java/dev/kske/eventbus/core/handler/ReflectiveEventHandler.java @@ -1,17 +1,18 @@ -package dev.kske.eventbus.core; +package dev.kske.eventbus.core.handler; import java.lang.reflect.*; +import dev.kske.eventbus.core.*; import dev.kske.eventbus.core.Event.USE_PARAMETER; /** - * Internal representation of an event handling method. + * An event handler wrapping a method annotated with {@link Event} and executing it using + * reflection. * * @author Kai S. K. Engelbart - * @since 0.0.1 - * @see EventBus + * @since 1.2.0 */ -final class EventHandler implements Comparable { +public final class ReflectiveEventHandler implements EventHandler { private final Object listener; private final Method method; @@ -21,7 +22,7 @@ final class EventHandler implements Comparable { private final int priority; /** - * Constructs an event handler. + * Constructs a reflective event handler. * * @param listener the listener containing the handler * @param method the handler method @@ -30,10 +31,10 @@ final class EventHandler implements Comparable { * @param defPriority the predefined priority (default or listener-level) * @throws EventBusException if the method or the annotation do not comply with the * specification - * @since 0.0.1 + * @since 1.2.0 */ - EventHandler(Object listener, Method method, Event annotation, boolean defPolymorphism, - int defPriority) throws EventBusException { + public ReflectiveEventHandler(Object listener, Method method, Event annotation, + boolean defPolymorphism, int defPriority) throws EventBusException { this.listener = listener; this.method = method; useParameter = annotation.value() == USE_PARAMETER.class; @@ -61,45 +62,13 @@ final class EventHandler implements Comparable { method.setAccessible(true); } - /** - * Compares this to another event handler based on priority. In case of equal priority a - * non-zero value based on hash codes is returned. - *

- * This is used to retrieve event handlers in descending order of priority from a tree set. - * - * @since 0.0.1 - */ @Override - public int compareTo(EventHandler other) { - int priority = other.priority - this.priority; - if (priority == 0) - priority = listener.hashCode() - other.listener.hashCode(); - return priority == 0 ? hashCode() - other.hashCode() : priority; - } - - @Override - public String toString() { - return String.format( - "EventHandler[method=%s, eventType=%s, useParameter=%b, polymorphic=%b, priority=%d]", - method, eventType, useParameter, polymorphic, priority); - } - - /** - * Executes the event handler. - * - * @param event the event used as the method parameter - * @throws EventBusException if the event handler isn't accessible or has an invalid - * signature - * @throws InvocationTargetException if the handler throws an exception - * @throws EventBusException if the handler has the wrong signature or is inaccessible - * @since 0.0.1 - */ - void execute(Object event) throws EventBusException, InvocationTargetException { + public void execute(Object event) throws EventBusException, InvocationTargetException { try { if (useParameter) - method.invoke(listener, event); + method.invoke(getListener(), event); else - method.invoke(listener); + method.invoke(getListener()); } catch (IllegalArgumentException e) { throw new EventBusException("Event handler rejected target / argument!", e); } catch (IllegalAccessException e) { @@ -107,29 +76,30 @@ final class EventHandler implements Comparable { } } - /** - * @return the listener containing this handler - * @since 0.0.1 - */ - Object getListener() { return listener; } + @Override + public String toString() { + return String.format( + "ReflectiveEventHandler[eventType=%s, polymorphic=%b, priority=%d, method=%s, useParameter=%b]", + eventType, polymorphic, priority, method, useParameter); + } - /** - * @return the event type this handler listens for - * @since 0.0.3 - */ - Class getEventType() { return eventType; } + @Override + public Object getListener() { + return listener; + } - /** - * @return the priority of this handler - * @since 0.0.1 - * @see Priority - */ - int getPriority() { return priority; } + @Override + public Class getEventType() { + return eventType; + } - /** - * @return whether this handler is polymorphic - * @since 1.0.0 - * @see Polymorphic - */ - boolean isPolymorphic() { return polymorphic; } + @Override + public int getPriority() { + return priority; + } + + @Override + public boolean isPolymorphic() { + return polymorphic; + } } diff --git a/event-bus-core/src/main/java/dev/kske/eventbus/core/handler/package-info.java b/event-bus-core/src/main/java/dev/kske/eventbus/core/handler/package-info.java new file mode 100644 index 0000000..fa3165a --- /dev/null +++ b/event-bus-core/src/main/java/dev/kske/eventbus/core/handler/package-info.java @@ -0,0 +1,8 @@ +/** + * Contains the internal representation of event handling methods. + * + * @author Kai S. K. Engelbart + * @since 1.2.0 + * @see dev.kske.eventbus.core.handler.EventHandler + */ +package dev.kske.eventbus.core.handler; diff --git a/event-bus-core/src/test/java/dev/kske/eventbus/core/DispatchTest.java b/event-bus-core/src/test/java/dev/kske/eventbus/core/DispatchTest.java index 5ba883e..250fc26 100644 --- a/event-bus-core/src/test/java/dev/kske/eventbus/core/DispatchTest.java +++ b/event-bus-core/src/test/java/dev/kske/eventbus/core/DispatchTest.java @@ -26,6 +26,10 @@ class DispatchTest { void registerListener() { bus = new EventBus(); bus.registerListener(this); + bus.registerListener(SimpleEvent.class, e -> { + ++hits; + assertEquals(4, hits); + }); } /** @@ -52,9 +56,9 @@ class DispatchTest { assertEquals( "Event handler execution order for class dev.kske.eventbus.core.SimpleEvent (3 handler(s)):\n" + "==========================================================================================\n" - + "EventHandler[method=void dev.kske.eventbus.core.DispatchTest.onSimpleEventFirst(), eventType=class dev.kske.eventbus.core.SimpleEvent, useParameter=false, polymorphic=true, priority=200]\n" - + "EventHandler[method=static void dev.kske.eventbus.core.DispatchTest.onSimpleEventSecond(), eventType=class dev.kske.eventbus.core.SimpleEvent, useParameter=false, polymorphic=false, priority=150]\n" - + "EventHandler[method=void dev.kske.eventbus.core.DispatchTest.onSimpleEventThird(dev.kske.eventbus.core.SimpleEvent), eventType=class dev.kske.eventbus.core.SimpleEvent, useParameter=true, polymorphic=false, priority=100]\n" + + "ReflectiveEventHandler[eventType=class dev.kske.eventbus.core.SimpleEvent, polymorphic=true, priority=200, method=void dev.kske.eventbus.core.DispatchTest.onSimpleEventFirst(), useParameter=false]\n" + + "ReflectiveEventHandler[eventType=class dev.kske.eventbus.core.SimpleEvent, polymorphic=false, priority=150, method=static void dev.kske.eventbus.core.DispatchTest.onSimpleEventSecond(), useParameter=false]\n" + + "CallbackEventHandler[eventType=class dev.kske.eventbus.core.SimpleEvent, polymorphic=false, priority=100]\n" + "==========================================================================================", executionOrder); } @@ -72,12 +76,4 @@ class DispatchTest { ++hits; assertEquals(3, hits); } - - @Event - @Polymorphic(false) - @Priority(100) - void onSimpleEventThird(SimpleEvent event) { - ++hits; - assertEquals(4, hits); - } } From d3abb0aca3ef6d8631597fd05319bf7cd6a33861 Mon Sep 17 00:00:00 2001 From: kske Date: Thu, 4 Nov 2021 15:54:36 +0100 Subject: [PATCH 2/3] Improve parameter naming for listener registration --- .../java/dev/kske/eventbus/core/EventBus.java | 59 ++++++++++--------- .../eventbus/core/handler/EventHandler.java | 2 +- 2 files changed, 31 insertions(+), 30 deletions(-) diff --git a/event-bus-core/src/main/java/dev/kske/eventbus/core/EventBus.java b/event-bus-core/src/main/java/dev/kske/eventbus/core/EventBus.java index ec467f8..42060b7 100644 --- a/event-bus-core/src/main/java/dev/kske/eventbus/core/EventBus.java +++ b/event-bus-core/src/main/java/dev/kske/eventbus/core/EventBus.java @@ -256,67 +256,68 @@ public final class EventBus { * Registers a callback listener, which is a consumer that is invoked when an event occurs. The * listener is not polymorphic and has the {@link #DEFAULT_PRIORITY}. * - * @param the event type the listener listens for - * @param eventType the event type the listener listens for - * @param callback the callback that is invoked when an event occurs + * @param the event type the listener listens for + * @param eventType the event type the listener listens for + * @param eventListener the callback that is invoked when an event occurs * @since 1.2.0 * @see #registerListener(Class, Consumer, boolean, int) */ - public void registerListener(Class eventType, Consumer callback) { - registerListener(eventType, callback, false, DEFAULT_PRIORITY); + public void registerListener(Class eventType, Consumer eventListener) { + registerListener(eventType, eventListener, false, DEFAULT_PRIORITY); } /** * Registers a callback listener, which is a consumer that is invoked when an event occurs. The * listener has the {@link #DEFAULT_PRIORITY}. * - * @param the event type the listener listens for - * @param eventType the event type the listener listens for - * @param callback the callback that is invoked when an event occurs - * @param polymorphic whether the listener is also invoked for subtypes of the event type + * @param the event type the listener listens for + * @param eventType the event type the listener listens for + * @param eventListener the callback that is invoked when an event occurs + * @param polymorphic whether the listener is also invoked for subtypes of the event type * @since 1.2.0 * @see #registerListener(Class, Consumer, boolean, int) */ - public void registerListener(Class eventType, Consumer callback, + public void registerListener(Class eventType, Consumer eventListener, boolean polymorphic) { - registerListener(eventType, callback, polymorphic, DEFAULT_PRIORITY); + registerListener(eventType, eventListener, polymorphic, DEFAULT_PRIORITY); } /** * Registers a callback listener, which is a consumer that is invoked when an event occurs. The * listener is not polymorphic. * - * @param the event type the listener listens for - * @param eventType the event type the listener listens for - * @param callback the callback that is invoked when an event occurs - * @param priority the priority to assign to the listener + * @param the event type the listener listens for + * @param eventType the event type the listener listens for + * @param eventListener the callback that is invoked when an event occurs + * @param priority the priority to assign to the listener * @since 1.2.0 * @see #registerListener(Class, Consumer, boolean, int) */ - public void registerListener(Class eventType, Consumer callback, int priority) { - registerListener(eventType, callback, false, priority); + public void registerListener(Class eventType, Consumer eventListener, int priority) { + registerListener(eventType, eventListener, false, priority); } /** * Registers a callback listener, which is a consumer that is invoked when an event occurs. * - * @param the event type the listener listens for - * @param eventType the event type the listener listens for - * @param callback the callback that is invoked when an event occurs - * @param polymorphic whether the listener is also invoked for subtypes of the event type - * @param priority the priority to assign to the listener + * @param the event type the listener listens for + * @param eventType the event type the listener listens for + * @param eventListener the callback that is invoked when an event occurs + * @param polymorphic whether the listener is also invoked for subtypes of the event type + * @param priority the priority to assign to the listener * @since 1.2.0 */ - public void registerListener(Class eventType, Consumer callback, boolean polymorphic, + public void registerListener(Class eventType, Consumer eventListener, + boolean polymorphic, int priority) { - Objects.requireNonNull(callback); - if (registeredListeners.contains(callback)) - throw new EventBusException(callback + " already registered!"); + Objects.requireNonNull(eventListener); + if (registeredListeners.contains(eventListener)) + throw new EventBusException(eventListener + " already registered!"); logger.log(Level.INFO, "Registering callback event listener {0}", - callback.getClass().getName()); + eventListener.getClass().getName()); - registeredListeners.add(callback); - bindHandler(new CallbackEventHandler(eventType, callback, polymorphic, priority)); + registeredListeners.add(eventListener); + bindHandler(new CallbackEventHandler(eventType, eventListener, polymorphic, priority)); } /** diff --git a/event-bus-core/src/main/java/dev/kske/eventbus/core/handler/EventHandler.java b/event-bus-core/src/main/java/dev/kske/eventbus/core/handler/EventHandler.java index 60fc059..30147a6 100644 --- a/event-bus-core/src/main/java/dev/kske/eventbus/core/handler/EventHandler.java +++ b/event-bus-core/src/main/java/dev/kske/eventbus/core/handler/EventHandler.java @@ -45,7 +45,7 @@ public interface EventHandler { int getPriority(); /** - * @return whether this handler is polymorphic + * @return whether this handler also accepts subtypes of the event type * @since 1.2.0 * @see Polymorphic */ From c614beb0631c08f45901c06521e1b49dff025c09 Mon Sep 17 00:00:00 2001 From: kske Date: Thu, 4 Nov 2021 15:55:24 +0100 Subject: [PATCH 3/3] Make CallbackEventHandler final --- .../dev/kske/eventbus/core/handler/CallbackEventHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/event-bus-core/src/main/java/dev/kske/eventbus/core/handler/CallbackEventHandler.java b/event-bus-core/src/main/java/dev/kske/eventbus/core/handler/CallbackEventHandler.java index 0bd1541..faf5a6c 100644 --- a/event-bus-core/src/main/java/dev/kske/eventbus/core/handler/CallbackEventHandler.java +++ b/event-bus-core/src/main/java/dev/kske/eventbus/core/handler/CallbackEventHandler.java @@ -9,7 +9,7 @@ import java.util.function.Consumer; * @author Kai S. K. Engelbart * @since 1.2.0 */ -public class CallbackEventHandler implements EventHandler { +public final class CallbackEventHandler implements EventHandler { private final Class eventType; private final Consumer callback;