Implementation of Return Injection
This commit is contained in:
@@ -22,15 +22,19 @@ public class AsyncEventLoop extends BaseEventLoop {
|
|||||||
Class<? extends Event> eventType = event.getClass();
|
Class<? extends Event> eventType = event.getClass();
|
||||||
if (handlers.containsKey(eventType)) {
|
if (handlers.containsKey(eventType)) {
|
||||||
for (ExecutorLink link : handlers.get(eventType)) {
|
for (ExecutorLink link : handlers.get(eventType)) {
|
||||||
|
Object preprocessResult = null;
|
||||||
if (link.getPreprocessMethod() != null) {
|
if (link.getPreprocessMethod() != null) {
|
||||||
try {
|
try {
|
||||||
link.getPreprocessMethod().invoke(link.object, event);
|
preprocessResult = link.getPreprocessMethod().invoke(link.object, event);
|
||||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||||
log.error("Exception caught while attempting to run event preprocessing for {}.", eventType.getSimpleName(), e);
|
log.error("Exception caught while attempting to run event preprocessing for {}.", eventType.getSimpleName(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
if (link.getResultInjection() != null)
|
||||||
|
link.getMethod().invoke(link.object, event, preprocessResult);
|
||||||
|
else
|
||||||
link.getMethod().invoke(link.object, event);
|
link.getMethod().invoke(link.object, event);
|
||||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||||
log.error("Exception caught while attempting to dispatch {}.", eventType.getSimpleName(), e);
|
log.error("Exception caught while attempting to dispatch {}.", eventType.getSimpleName(), e);
|
||||||
@@ -65,23 +69,55 @@ public class AsyncEventLoop extends BaseEventLoop {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (preprocessors.containsKey(annotation.eventName()))
|
if (preprocessors.containsKey(annotation.methodName()))
|
||||||
log.warn("Attempted to register multiple EventPreprocessors for the event {}. Please note, that only the last one will be registered.", annotation.eventName());
|
log.warn("Attempted to register multiple EventPreprocessors for the event {}. Please note, that only the last one will be registered.", annotation.methodName());
|
||||||
preprocessors.put(annotation.eventName(), method);
|
preprocessors.put(annotation.methodName() + ":" + firstParamType.getSimpleName(), method);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for (Method method : object.getClass().getDeclaredMethods()) {
|
for (Method method : object.getClass().getDeclaredMethods()) {
|
||||||
EventHandler annotation = method.getAnnotation(EventHandler.class);
|
EventHandler annotation = method.getAnnotation(EventHandler.class);
|
||||||
|
|
||||||
if (notValidEventHandler(annotation, method))
|
if (annotation == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (!Modifier.isPublic(method.getModifiers())) {
|
||||||
|
log.error("Unable to register {} as an EventHandler. Method must have a 'private' access modifier.", method.toString());
|
||||||
|
continue;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (method.getParameterCount() == 0) {
|
||||||
|
log.error("Unable to register {} as an EventHandler. Method must at least one argument.", method.toString());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Class<?> firstParamType = method.getParameterTypes()[0];
|
||||||
|
if (!Event.class.isAssignableFrom(firstParamType)) {
|
||||||
|
log.error("Unable to register {} as an EventHandler. First parameter type must implement 'Event' interface.", method.toString());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
@SuppressWarnings("unchecked") Class<? extends Event> eventType = (Class<? extends Event>) method.getParameterTypes()[0];
|
@SuppressWarnings("unchecked") Class<? extends Event> eventType = (Class<? extends Event>) method.getParameterTypes()[0];
|
||||||
|
|
||||||
|
Method preprocessMethod = preprocessors.get(method.getName() + ":" + eventType.getSimpleName());
|
||||||
|
Class resultInjection = null;
|
||||||
|
if (preprocessMethod.getReturnType() != void.class && method.getParameterCount() == 2 && preprocessMethod.getReturnType().equals(method.getParameterTypes()[1]))
|
||||||
|
resultInjection = preprocessMethod.getReturnType();
|
||||||
|
|
||||||
|
if (resultInjection == null && method.getParameterCount() > 1) {
|
||||||
|
log.error("Unable to register {} as an EventHandler. Method has {} arguments, but no EventPreprocessors found to provide DI for type {}", method.toString(), method.getParameterCount(), method.getParameterTypes()[1].toString());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resultInjection == null && preprocessMethod.getReturnType() != void.class) {
|
||||||
|
log.warn("DI registration for EventHandler {} failed. Injection target not found", method.toString());
|
||||||
|
}
|
||||||
|
|
||||||
List<ExecutorLink> eventHandlers = handlers.computeIfAbsent(eventType, s -> new ArrayList<>());
|
List<ExecutorLink> eventHandlers = handlers.computeIfAbsent(eventType, s -> new ArrayList<>());
|
||||||
eventHandlers.add(new ExecutorLink(annotation.priority().getValue(), annotation.ignoreCancelled(), method, object, preprocessors.remove(method.getName())));
|
eventHandlers.add(new ExecutorLink(annotation.priority().getValue(), annotation.ignoreCancelled(), method, object, preprocessMethod, resultInjection));
|
||||||
eventHandlers.sort(Comparator.comparingInt(o -> o.priority));
|
eventHandlers.sort(Comparator.comparingInt(o -> o.priority));
|
||||||
|
|
||||||
|
preprocessors.remove(method.getName() + ":" + eventType.getSimpleName());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Map.Entry<String, Method> preprocessor : preprocessors.entrySet())
|
for (Map.Entry<String, Method> preprocessor : preprocessors.entrySet())
|
||||||
@@ -100,6 +136,7 @@ public class AsyncEventLoop extends BaseEventLoop {
|
|||||||
private final Method method;
|
private final Method method;
|
||||||
private final Object object;
|
private final Object object;
|
||||||
private final Method preprocessMethod;
|
private final Method preprocessMethod;
|
||||||
|
private final Class resultInjection;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,5 +8,5 @@ import java.lang.annotation.*;
|
|||||||
@Inherited
|
@Inherited
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
public @interface EventPreprocessor {
|
public @interface EventPreprocessor {
|
||||||
String eventName();
|
String methodName();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,6 @@ public class AsyncEventLoopTest {
|
|||||||
|
|
||||||
asyncEventLoop.callEvent(testEvent);
|
asyncEventLoop.callEvent(testEvent);
|
||||||
|
|
||||||
Assert.assertEquals("Event handler was not called", "Hello from Async Event Handler!", testEvent.getDenyReason());
|
Assert.assertEquals("Event handler was not called", "Hello! This is a message from Sync portion of the event", testEvent.getDenyReason());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,24 @@
|
|||||||
package ru.core.events.handlers;
|
package ru.core.events.handlers;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import mc.core.events.EventHandler;
|
import mc.core.events.EventHandler;
|
||||||
import mc.core.events.LoginEvent;
|
import mc.core.events.LoginEvent;
|
||||||
import mc.core.events.async.EventPreprocessor;
|
import mc.core.events.async.EventPreprocessor;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class AsyncEventHandler {
|
public class AsyncEventHandler {
|
||||||
|
|
||||||
@EventHandler
|
@EventPreprocessor(methodName = "onLogin")
|
||||||
public void onLogin(LoginEvent event) {
|
|
||||||
event.setDenyReason("Hello from Async Event Handler!");
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventPreprocessor(eventName = "onLogin")
|
|
||||||
public void onLoginPreprocess(LoginEvent event) {
|
public void onLoginPreprocess(LoginEvent event) {
|
||||||
|
event.setDenyReason("Hello! This is a message from Async event preprocessor.");
|
||||||
|
|
||||||
|
// Представим, что здесь мы выполнили запрос к БД
|
||||||
|
// и это значение - кол-во денег у игрока
|
||||||
|
/*return 20D;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onLogin(LoginEvent event) { // money здесь будет равно тому, что вернул onLoginPreprocess
|
||||||
|
event.setDenyReason("Hello! This is a message from Sync portion of the event");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user