使用Java反射进行事件处理
好吧,这很难解释。我会尽力的
受Bukkit事件系统的启发,您可以通过使用@EventHandler使事件处理程序无效
例如:
@EventHandler
public void aRandomName(PlayerMoveEvent ev) {
}
如您所见,方法的名称并不重要。传递哪个事件由事件参数类型决定
所有事件都扩展事件类。 我已经编写了一些代码,我认为这些代码可以工作,除了一件事
public List<Object> eventContainers;
public void fireEvent(Event e) {
Method[] methods;
for (Object o : eventContainers) {
Object[] classes = o.getClass().getClasses();
for (Object clss : classes) {
methods = clss.getClass().getMethods();
for (Method m : methods) {
if (m.getAnnotation(EventHandler.class) != null) {
try {
Class[] requiredTypes = m.getParameterTypes();
for(Class cl : requiredTypes) {
if(e.equals(cl)) {
m.invoke(clss, e);
}
}
} catch (IllegalAccessException ex) {
} catch (IllegalArgumentException ex) {
} catch (InvocationTargetException ex) {
}
}
}
}
}
}
我的代码的作用是: 循环遍历eventContainers中的所有类,查找具有@EventHandler注释的方法,并将指定的事件发送给该方法。但是,我想看看fireEvent(event e)中给定的事件是什么类型的事件,然后看看需要这种类型的事件参数的方法。我该怎么做?我想
Class[] requiredTypes = m.getParameterTypes();
for(Class cl : requiredTypes) {
if(e.equals(cl)) {
m.invoke(clss, e);
}
}
这是行不通的
最终,我希望能够将事件传递给插件。像这样:
EventManager.fireEvent(new PlayerMoveEvent(player));
它将被发送到所有插件和具有
@EventHandler
public void aVoid(PlayerMoveEvent e) {
//stuff
}
如果你有任何问题,我会尽量解释得更好。提前感谢您的帮助
# 1 楼答案
假设
EventHandler
注释的方法只有一个参数我没有包括任何异常处理
获取事件处理程序候选类的所有方法并迭代它们。如果方法具有
@EventHandler
注释,则获取其参数类型列表。如果它只有一个参数,并且该类型可从事件类型e.getClass()
分配,则在传递事件时调用它# 2 楼答案
我现在已将代码修改为工作事件系统D非常感谢Anderschuller
我记住了所有的答案,谢谢大家
# 3 楼答案
您的代码使用
e.equals(cl)
,它将Event
的实例与Class
的实例(一个Event
实例的类)进行比较—这将永远不会返回true。您想做的是:或者,如果您希望用
@EventHandler
注释的方法处理其方法签名定义的类的所有子类(即像handle(Event e)
这样的方法将用PlayerMoveEvents
以及所有其他事件调用),那么您需要:有关更多信息,请参见^{} Javadoc here
请注意,我认为代码中还有一些其他问题。例如,应使用类的实例调用
Method.invoke
,该类包含用@EventHandler
注释的方法。您的代码有点不清楚,但我相信这应该是:另外,通过调用
o.getClass().getClasses()
,您正在迭代o
类中定义的类-您可能希望直接迭代o
类的方法,即:# 4 楼答案
您可以使用
method.getGenericParameterTypes()
从Method
获取参数类型,因此:不确定这是否是你想要的